防止重复保存在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
删除shopt
和PROMPT_COMMAND
行不能解决问题。
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 -a
。 history -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可以通过
- 修复
history -a
改善这种情况仅当它不内存匹配任何历史,而不仅仅是最后一个写入新的数据。 - 如果设置了
erasedups
设置,则读取文件时去除重复历史记录。然后,新终端中的简单history -w
将清除历史文件,而不是上面的愚蠢脚本。
你有没有解决过这个问题?我的/ etc/profile文件看起来像这样(在Mac)和我有同样的问题: #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
看到这个问题http://unix.stackexchange.com/questions/48713/how-can-i-remove-duplicates -in-my-bash-history-preserving-order – Nathan 2014-01-15 19:32:38
这是编程中固有的问题,与程序员使用的特定工具有关。我很困惑这个问题会被视为“无关紧要”(至少5人以上)。冗余的.bash_history对我来说是一个长期的烦恼,现在已经解决了。 然而,这个问题可以移到Unix stackexchange站点。 – 2017-06-15 20:10:01