Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent duplicates from being saved in bash history [closed]

I'm trying to prevent bash from saving duplicate commands to my history. Here's what I've got:

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:

$ 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.

like image 420
JPLemme Avatar asked Dec 03 '08 18:12

JPLemme


People also ask

How do I turn off bash history?

How to permanently disable bash history using set command. Again add set +o history to the end of to a new /etc/profile. d/disable. history.

How do I make bash history Unlimited?

In bash 4.3 and later you can also use HISTSIZE=-1 HISTFILESIZE=-1 : n. Setting HISTSIZE to a value less than zero causes the history list to be unlimited (setting it 0 zero disables the history list). o.

How do I edit bash history files?

In the Terminal just type open -e ~/. bash_history . This command will open the file with TextEdit, you can choose any other text editor, of course. Modify the file and save.

What is stored in bash history?

The background. In Bash, your command history is stored in a file ( . bash_history ) in your home directory.


1 Answers

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.

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.

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.

I use my own script to clean up the history file on demand.

# 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 } 

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.

Bash can improve the situation by

  1. fix history -a to only write new data if it does not match any history in memory, not just the last one.
  2. de-deduplicate history when files are read if erasedups setting is set . A simple history -w in a new terminal would then clean up the history file instead of the silly script above.
like image 64
raychi Avatar answered Sep 18 '22 08:09

raychi