防止重复保存在bash历史中

防止重复保存在bash历史中

问题描述:

我试图阻止bash将重复命令保存到我的历史记录中。这里是我得到的:防止重复保存在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 

我在做什么错?

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

+1

你有没有解决过这个问题?我的/ etc/profile文件看起来像这样(在M​​ac)和我有同样的问题: #http://blog.macromates.com/2008/working-with-history-in-bash/ #HTTP: //www.ducea.com/2006/05/15/linux-tips-take-control-of-your-bash_history/ 出口HISTCONTROL = erasedups 出口HISTSIZE = 10000 出口HISTTIMEFORMAT =“%F-% T%t“ shopt -s histappend (试图格式化这一半体面,不容易) – joedevon 2011-01-08 01:23:16

+0

看到这个问题http://unix.stackexchange.com/questions/48713/how-can-i-remove-duplicates -in-my-bash-history-preserving-order – Nathan 2014-01-15 19:32:38

+1

这是编程中固有的问题,与程序员使用的特定工具有关。我很困惑这个问题会被视为“无关紧要”(至少5人以上)。冗余的.bash_history对我来说是一个长期的烦恼,现在已经解决了。 然而,这个问题可以移到Unix stackexchange站点。 – 2017-06-15 20:10:01

export HISTCONTROL=ignoreboth 

问题肯定是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 -ahistory -w应该写出没有任何重复的当前历史记录,因此如果您不介意并发问题,请使用它。

这里是我用什么..

[[email protected] ~]$ 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 
[[email protected] ~]$ 

和工作

[[email protected] ~]$ pwd 
/Users/XXX 
[[email protected] ~]$ pwd 
/Users/XXX 
[[email protected] ~]$ history | grep pwd | wc -l 
     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

据我所知,这是不可能做你想做的。我认为这是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]++' [email protected] 
} 

# 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" [email protected] 
    else 
     cat [email protected] 
    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可以通过

  1. 修复history -a改善这种情况仅当它不内存匹配任何历史,而不仅仅是最后一个写入新的数据。
  2. 如果设置了erasedups设置,则读取文件时去除重复历史记录。然后,新终端中的简单history -w将清除历史文件,而不是上面的愚蠢脚本。