'history -a vs -w in BASH. How to replace/append and ignore/erase duplicates?

I'm writing my PROMPT_COMMAND="history -a;$PROMPT_COMMAND" but I still get some duplicates from different terminal sessions. It seems I still will get some duplicates but I get less using the command PROMPT_COMMAND="history -w;$PROMPT_COMMAND".

I know I can do the history -a;history -c; history -r but I don't want them all synced. I only want that to occur when I call history -n. I'm basically down to using either history -a or history -w but I can't seem to find the difference between the two. Which one would be better to have to avoid as many duplicates as possible.



Solution 1:[1]

You stated two questions:

What is the difference between history -a and history -w?

history -a will append your current session history to the content of the history file.

history -w will replace the content of the history file with your current session history.

Which one avoids more duplicates?

Theoretically neither. Neither -a nor -w checks for duplicates. You can argue that -w avoids more duplicates but only because it removes the previous content of the history file. So any potential duplicate entries in the file are eliminated. Along with anything else in the file.


Background information:

Bash has a history feature. In most distros bash is configured to have history enabled by default.

For the most basic use cases it works as follows: all commands typed in the prompt and executed will be put in history. If you press the up arrow on an empty prompt it will recall the last command entered. Press up again and it will recall the second to last command.

If you want more advanced features, like duplicate avoidance, you will first need to understand the following: in any bash session there are at least two versions of history. One is the history that is stored in the memory of the currently running bash process (the session history). The other is the history saved on disk (the history file).

When using bash and using the history feature in bash you typically only work with the session history. the history file is only touched on certain events. such events are for example: bash startup, bash shutdown, or invocation of history -a or history -w.

A common bash configuration is as follows: on bash startup read from history file to session history. While running and executing commands from prompt only manipulate the session history. on shutdown replace content of history file with session history.

Bash has features to avoid some duplicates in the session history. But none (that i know of) in the history file.


Bash features to avoid some duplicates:

set the special bash variable HISTCONTROL to ignoredups. effect is if you reexecute the same command immediately again the duplicate will not be saved to session history. But if you reexecute a command from history after executing other commands in between the duplicate will still be saved to session history.

set the special bash variable HISTCONTROL to erasedups. effect is erase any existing history entry matching the currently entered command. but note it only does so in the current session history. It does not search for duplicates in the history file. It will also not prevent duplicates from entering your session history when using history -n (read entries from history file to session history).


more details in the bash manual:

about the history command.

about the special variable HISTCONTROL.

Solution 2:[2]

you can avoid duplicates by using this

export HISTCONTROL=ignoredups

You can look at this for more information:

http://stefaanlippens.net/bashduplicates

Solution 3:[3]

Use BASH variable PROMPT_COMMAND with history and using sort and uniq commands:

$> export PROMPT_COMMAND="history -a && history -c && sort ~/.bash_history | uniq > ~/.bash_history_new && rm ~/.bash_history && mv ~/.bash_history_new ~/.bash_history && history -r"

With this you don't need to set shopt -s histappend and do export HISTCONTROL=erasedups.

This will keep your history and history file without duplicates on-the-fly. You can play with keeping history in order commands has been typed (hint: use line numbers in history, sort from specific line start position and after removing duplicates do sort again with line numbers).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 reader_1000
Solution 3