防止重复项保存在 bash 历史记录中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/338285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Prevent duplicates from being saved in bash history
提问by JPLemme
I'm trying to prevent bash
from saving duplicate commands to my history. Here's what I've got:
我试图防止bash
将重复的命令保存到我的历史记录中。这是我所拥有的:
shopt -s histappend
export HISTIGNORE='&:ls:cd ~:cd ..:[bf]g:exit:h:history'
export HISTCONTROL=erasedups
export PROMPT_COMMAND='history -a'
This works fine while I'm logged in and .bash_history
is in memory. For example:
这在我登录并.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
But when I log back in, my history file looks like this:
但是当我重新登录时,我的历史文件如下所示:
$ 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
What am I doing wrong?
我究竟做错了什么?
EDIT: Removing the shopt
and PROMPT_COMMAND
lines from .bashrc
does not fix the problem.
编辑:删除shopt
和PROMPT_COMMAND
行.bashrc
并不能解决问题。
回答by raychi
As far as I know, it is not possible to do what you want. I see this as a bug in bash's history processing that could be improved.
据我所知,不可能做你想做的事。我认为这是 bash 历史处理中的一个错误,可以改进。
export HISTCONTROL=ignoreboth:erasedups # no duplicate entries
shopt -s histappend # append history file
export PROMPT_COMMAND="history -a" # update histfile after every command
This will keep the in memory history unique, but while it does saves history from multiple sessions into the same file, it doesn't keep the history in the file itself unique. history -a
will write the new command to the file unless it's the same as the one immediately before it. It will not do a full de-duplication like the erasedups
setting does in memory.
这将使内存中的历史记录保持唯一,但虽然它确实将多个会话的历史记录保存到同一个文件中,但它不会使文件本身中的历史记录保持唯一。history -a
将新命令写入文件,除非它与之前的命令相同。它不会像erasedups
内存中的设置那样执行完全重复数据删除。
To see this silliness in action, start a new terminal session, examine the history, and you'll see repeated entries, say ls
. Now run the ls
command, and all the duplicated ls
will be removed from the history in memory, leaving only the last one. The in memory history becomes shorter as you run commands that are duplicated in the history file, yet the history file itself continues to grow.
要查看这种愚蠢行为,请启动一个新的终端会话,检查历史记录,您将看到重复的条目,例如ls
。现在运行该ls
命令,所有重复的ls
将从内存中的历史记录中删除,只留下最后一个。当您运行历史文件中重复的命令时,内存中的历史会变短,但历史文件本身会继续增长。
I use my own script to clean up the history file on demand.
我使用自己的脚本按需清理历史文件。
# remove duplicates while preserving input order
function dedup {
awk '! x[$ 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
]++' $@
}
# 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
}
I'd love to hear more elegant ways to do this.
我很想听听更优雅的方法来做到这一点。
Note: the script won't work if you enable timestamp in history via HISTTIMEFORMAT.
注意:如果您通过 HISTTIMEFORMAT 在历史中启用时间戳,该脚本将不起作用。
Bash can improve the situation by
Bash 可以通过以下方式改善情况
- fix
history -a
to only write new data if it does not match any history in memory, not just the last one. - de-deduplicate history when files are read if
erasedups
setting is set . A simplehistory -w
in a new terminal would then clean up the history file instead of the silly script above.
- 修复
history -a
仅在新数据与内存中的任何历史记录不匹配时才写入新数据,而不仅仅是最后一个。 - 如果
erasedups
设置了设置,则在读取文件时去重复历史记录。一个简单history -w
的新终端然后会清理历史文件而不是上面的愚蠢脚本。
回答by raychi
The problem is definitely the histappend
. Tested and confirmed on my system.
问题肯定是histappend
. 在我的系统上进行了测试和确认。
My relevant environment is:
我的相关环境是:
export HISTCONTROL=ignoreboth
Now that I think about it, the problem is probably with the history -a
. history -w
should write the current history without any duplicates, so use that if you don't mind the concurrency issues.
现在想想,问题可能出在history -a
. history -w
应该写入没有任何重复的当前历史记录,因此如果您不介意并发问题,请使用它。
回答by Robert Gamble
[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@ ~]$
回答by Venu Anuganti
Here is what I use..
这是我使用的..
[vanuganti@ ~]$ pwd
/Users/XXX
[vanuganti@ ~]$ pwd
/Users/XXX
[vanuganti@ ~]$ history | grep pwd | wc -l
1
and working
和工作
alias hist="history -a && hist.py"
回答by jserver
inside your .bash_profile add
在你的 .bash_profile 添加
#!/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
then put this on your path as hist.py and make it executable
然后将其作为 hist.py 放在您的路径上并使其可执行
##代码##now when you want the short list just type hist
现在,当您想要短列表时,只需键入 hist