当前位置:  开发笔记 > 编程语言 > 正文

防止在bash历史记录中保存重复项

如何解决《防止在bash历史记录中保存重复项》经验,为你挑选了2个好方法。

我正在尝试阻止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

我究竟做错了什么?

编辑:删除shoptPROMPT_COMMAND.bashrc不能解决问题.



1> raychi..:

据我所知,不可能做你想做的事.我认为这是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,新终端中的简单将清除历史文件而不是上面的愚蠢脚本.


@raychi只是检查一下,如果这仍然是我们接近2014年的最佳解决方案?
非常好的答案.如果您希望保留命令的时间顺序(而不是输入顺序),请通过替换`awk'来修改`dedup()`!x [$ 0] ++'$ @`与`tac $ @ | awk'!x [$ 0] ++'| tac`.

2> 小智..:

问题肯定是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应该编写当前历史记录而不重复,所以如果你不介意并发问题,请使用它.

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有