我正在尝试阻止bash
将重复命令保存到我的历史记录中。这就是我所拥有的:
shopt -s histappend
export HISTIGNORE='&:ls:cd ~:cd ..:[bf]g:exit:h:history'
export HISTCONTROL=erasedups
export PROMPT_COMMAND='history -a'
当我登录并且.bash_history
在内存中时,此功能正常。例如:
$ history
1 vi .bashrc
2 vi .alias
3 cd /cygdrive
4 cd ~jplemme
5 vi .bashrc
6 vi .alias
$ vi .bashrc
$ history
1 vi .alias
2 cd /cygdrive
3 cd ~jplemme
4 vi .alias
5 vi .bashrc
$ vi .alias
$ history
1 cd /cygdrive
2 cd ~jplemme
3 vi .bashrc
4 vi .alias
$ exit
但是当我重新登录时,我的历史文件看起来像这样:
$ history
1 vi .bashrc
2 vi .alias
3 cd /cygdrive
4 cd ~jplemme
5 vi .bashrc
6 vi .alias
7 vi .bashrc
8 vi .alias
我做错了什么?
编辑:从shopt
删除PROMPT_COMMAND
和.bashrc
行并不能解决问题。
答案 0 :(得分:34)
据我所知,不可能做你想做的事。我认为这是bash历史处理中可以改进的错误。
export HISTCONTROL=ignoreboth:erasedups # no duplicate entries
shopt -s histappend # append history file
export PROMPT_COMMAND="history -a" # update histfile after every command
这将使内存历史记录保持唯一,但是它确实将多个会话的历史记录保存到同一文件中,但它不会使文件本身的历史记录保持唯一。 history -a
会将新命令写入文件,除非它与之前的命令相同。它不会像erasedups
设置那样在内存中执行完全重复数据删除。
要查看此愚蠢行为,请启动新的终端会话,检查历史记录,然后您会看到重复的条目,例如ls
。现在运行ls
命令,所有重复的ls
将从内存中的历史记录中删除,只留下最后一个。当您运行历史文件中重复的命令时,内存历史记录会变短,但历史文件本身会继续增长。
我使用自己的脚本按需清理历史文件。
# remove duplicates while preserving input order
function dedup {
awk '! x[$0]++' $@
}
# removes $HISTIGNORE commands from input
function remove_histignore {
if [ -n "$HISTIGNORE" ]; then
# replace : with |, then * with .*
local IGNORE_PAT=`echo "$HISTIGNORE" | sed s/\:/\|/g | sed s/\*/\.\*/g`
# negated grep removes matches
grep -vx "$IGNORE_PAT" $@
else
cat $@
fi
}
# clean up the history file by remove duplicates and commands matching
# $HISTIGNORE entries
function history_cleanup {
local HISTFILE_SRC=~/.bash_history
local HISTFILE_DST=/tmp/.$USER.bash_history.clean
if [ -f $HISTFILE_SRC ]; then
\cp $HISTFILE_SRC $HISTFILE_SRC.backup
dedup $HISTFILE_SRC | remove_histignore >| $HISTFILE_DST
\mv $HISTFILE_DST $HISTFILE_SRC
chmod go-r $HISTFILE_SRC
history -c
history -r
fi
}
我很想听到更优雅的方式来做到这一点。
注意:如果您通过HISTTIMEFORMAT在历史记录中启用时间戳,则脚本将不起作用。
Bash可以通过
来改善这种情况history -a
只能写入新数据,如果它与内存中的任何历史记录都不匹配,而不仅仅是最后一个。erasedups
设置,则在读取文件时删除重复数据删除历史记录。然后,新终端中的简单history -w
将清除历史文件,而不是上面的愚蠢脚本。答案 1 :(得分:7)
问题绝对是histappend
。在我的系统上测试并确认。
我的相关环境是:
$ set | grep HIST
HISTFILE=/Users/hop/.bash_history
HISTFILESIZE=500
HISTIGNORE=' *:&:?:??'
HISTSIZE=500
$ export HISTCONTROL=erasedups
$ shopt | grep hist
cmdhist on
histappend off
histreedit off
histverify off
lithist off
现在我想到了,问题可能在于history -a
。 history -w
应该编写当前历史记录而不重复,所以如果你不介意并发问题,请使用它。
答案 2 :(得分:5)
export HISTCONTROL=ignoreboth
答案 3 :(得分:2)
这是我使用的..
[vanuganti@ ~]$ grep HIST .alias*
.alias:HISTCONTROL="erasedups"
.alias:HISTSIZE=20000
.alias:HISTIGNORE=ls:ll:"ls -altr":"ls -alt":la:l:pwd:exit:mc:su:df:clear:ps:h:history:"ls -al"
.alias:export HISTCONTROL HISTSIZE HISTIGNORE
[vanuganti@ ~]$
并且正在工作
[vanuganti@ ~]$ pwd
/Users/XXX
[vanuganti@ ~]$ pwd
/Users/XXX
[vanuganti@ ~]$ history | grep pwd | wc -l
1
答案 4 :(得分:1)
在你的.bash_profile内添加
alias hist="history -a && hist.py"
然后将其作为hist.py放在您的路径上并使其可执行
#!/usr/bin/env python
f = open('/Users/joe/.bash_history')
l = f.readlines()
l.reverse()
short = []
for s in l:
if s.rstrip() not in short:
short.append(s.rstrip())
short.reverse()
for s in short:
print s
现在当你想要短名单时只需输入hist