我试图防止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
我究竟做错了什么?
据我所知,这是不可能做你想要的。我认为这是一个bug,在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将新命令写入文件,除非它与之前一个相同。它不会像内存中的擦除设置那样进行完全重复数据删除。
要看到这个行动的蠢,开始一个新的终端会话,检查历史,你会看到重复的条目,说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可以改善的情况
>修复历史-a只写入新数据,如果它不匹配内存中的任何历史记录,而不只是最后一个。>在读取文件时删除重复数据删除历史记录。一个新的终端中的简单历史记录-w将清除历史文件,而不是上面的愚蠢的脚本。