10

I have the following line in my ~/.bashrc

export HISTCONTROL=ignoreboth:erasedups

However whenever I run somecommand it keeps adding the duplicated command into .bash_history like this

grep -w somecommand ~/.bash_history
somecommand
somecommand abc xyz
somecommand 123
somecommand
...

Why is this and how to prevent it?

phuclv
  • 2,086

3 Answers3

8

The erasedups option will remove duplicated lines limited by this two conditions:

  • The lines will be erased from the list in memory.
  • Only when a new command is going to be added to the list.

The list in memory is the output of history.
The whole list "in memory" will be written to file with history -w or when bash is closed (if histappend is not set).

So, if the list in memory is:

$ history
1  cmd1
2  cmd2
3  cmd3
4  cmd1
5  cmd2
6  export HISTCONTROL=ignoreboth:erasedups
7  history

It will become:

$ history
1  cmd2
2  cmd3
3  cmd2
4  export HISTCONTROL=ignoreboth:erasedups
5  cmd1
6  history

All cmd1 commands (except the one being appended) are removed.

If cmd2 is executed, all repeats of cmd2 are also removed (also history):

$ cmd2
$ history
1  cmd3
2  export HISTCONTROL=ignoreboth:erasedups
3  cmd1
4  cmd2
5  history

But even now, the file ~/.bash_history has not been modified. It still contains the list of commands from a previous session. Using grep on the file may show many duplicates (dups), including the commands just used (cmd1 and cmd2). A grep will only work correctly on the memory list:

$ history | grep cmd1

Once the list gets written to file (history -w) is it correct that only one instance of each command line used in the session.will be found with grep.

You can force an update of the disk file every time with:

$ PROMPT_COMMAND='history -w'
3

According to man bash:

A value of ignoredups causes lines matching the previous history entry to not be saved.

If you run somecommand twice in a row with no arguments, you should see only one consecutive entry.

Likewise if you run somecommand 123 twice in a row, it will only be added to the history once.

The commands in your list show no consecutive duplicates, so this feature is working as intended.

Wildcard
  • 36,499
  • 1
    ah, I thought that it will remove the previous duplicate entry. So it seems less useful than expected, because sometimes I run cmdA then cmdB then cmdA it still shows 2 cmdAs nearby – phuclv Oct 18 '17 at 03:43
  • @LưuVĩnhPhúc, I'm curious: are you trying to get a clean readable history list, or are you trying to easily re-execute commands you've run earlier? (If the latter, you might try using fc. – Wildcard Oct 24 '17 at 23:11
  • I constantly use Ctrl+R to find commands I've used and it shows many duplicates which is a bit annoying – phuclv Oct 25 '17 at 02:26
  • 4
    I believe that the question is about erasedups not ignoredups (please read the title). In any case, your answer does not explain such option –  Jul 01 '18 at 16:56
1

To uniqely record every new command is tricky. First you need to add to ~/.profile or similar:

HISTCONTROL=erasedups
PROMPT_COMMAND='history -w'

Then you need to add to ~/.bash_logout:

history -a
history -w
Zombo
  • 1
  • 5
  • 44
  • 63
  • 1
    There is no need to add anything to ~/.bash_logout. By default bash store the memory list to file on exit. –  Jul 01 '18 at 16:53