So my home directory does have a .bash_history file, but it refuses to grow any bigger for some reason. I've already changed the .bashrc
settings to set the history size to 99999 and the history file size limit to something similar.
Bash – How to preserve the history file of cygwin bash across independent sessions
bashcommand historycygwin;
Related Solutions
This is actually a really interesting behavior and I confess I have greatly underestimated the question at the beginning. But first the facts:
1. What works
The functionality can be achieved in several ways, though each works a bit differently. Note that, in each case, to have the history "transferred" to another terminal (updated), one has to press Enter in the terminal, where he/she wants to retrieve the history.
option 1:
shopt -s histappend HISTCONTROL=ignoredups PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
This has two drawbacks:
- At login (opening a terminal), the last command from the history file is read twice into the current terminal's history buffer;
- The buffers of different terminals do not stay in sync with the history file.
option 2:
HISTCONTROL=ignoredups PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
(Yes, no need for shopt -s histappend
and yes, it has to be history -c
in the middle of PROMPT_COMMAND
)
This version has also two important drawbacks:
- The history file has to be initialized. It has to contain at least one non-empty line (can be anything).
- The
history
command can give false output - see below.
[Edit] "And the winner is..."
option 3:
HISTCONTROL=ignoredups:erasedups shopt -s histappend PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
This is as far as it gets. It is the only option to have both erasedups
and common history working simultaneously.
This is probably the final solution to all your problems, Aahan.
2. Why does option 2 not seem to work (or: what really doesn't work as expected)?
As I mentioned, each of the above solutions works differently. But the most misleading interpretation of how the settings work comes from analysing the output of history
command. In many cases, the command can give false output. Why? Because it is executed before the sequence of other history
commands contained in the PROMPT_COMMAND
! However, when using the second or third option, one can monitor the changes of .bash_history
contents (using watch -n1 "tail -n20 .bash_history"
for example) and see what the real history is.
3. Why option 3 is so complicated?
It all lies in the way erasedups
works. As the bash manual states, "(...) erasedups
causes all previous lines matching the current line to be removed from the history list before that line is saved". So this is really what the OP wanted (and not just, as I previously thought, to have no duplicates appearing in sequence). Here's why each of the history -.
commands either has to or can not be in the PROMPT_COMMAND
:
history -n
has to be there beforehistory -w
to read from.bash_history
the commands saved from any other terminal,history -w
has to be there in order to save the new history to the file after bash has checked if the command was a duplicate,history -a
must not be placed there instead ofhistory -w
, because it will add to the file any new command, regardless of whether it was checked as a duplicate.history -c
is also needed because it prevents trashing the history buffer after each command,and finally,
history -r
is needed to restore the history buffer from file, thus finally making the history shared across terminal sessions.
Be aware that this solution will mess up the history order by putting all history from other terminals in front of the newest command entered in the current terminal. It also does not delete duplicate lines already in the history file unless you enter that command again.
Yes. You can copy the old history file to a new install. You can also merge it with old / new.
- If you do not have
HISTTIMEFORMAT
set the history file only holds commands. If it is set there is a timestamp preceded by a hash for each command:
#1122334455 command1 #1122334459 command2
Note however that if you issue e.g:
$ echo 'foo
> bar
> baz' >> some_file
It is going to be saved as:
#1122334459
echo 'foo
bar
baz' >> some_file
But history
is going to show:
4 CMD_TIME echo 'foo
5 CUR_TIME bar
6 CUR_TIME baz' >> some_file
Commands like:
$ foo | \
bar | \
baz
are preserved as one if you set shopt -s cmdhist
.
I use various but often something like:
HISTSIZE=500000
HISTFILESIZE=500000
# Ignore dupes and space commands
HISTCONTROL=ignoreboth
# Save and show timestamps
HISTTIMEFORMAT='%F %T '
# append to the history file, don't overwrite it
shopt -s histappend
# Save and reload the history after each command finishes
# This one I have a function to turn on/off. Effect is that commands are
# accessible in all terminals after execution.
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
- More on
shopt
. (Use$ shopt
to show current settings.) - More on
history
.
I also back up history files regularly and have some scripts and aliases to search history – even many years back in time. Sometimes I recall I did something similar to what I'm currently doing 1.5 years ago and can quickly look up in history.
As for timestamps I use two variants. history
shows with timestamps and another show without by temporarily setting HISTTIMEFORMAT
to "".
If timestamp is missing current time (approximately) is used. If timestamps are present history is sorted by times.
Thus:
.bash_history
(Timestamps simplified)
#timestamp 000012
some command
#timestamp 000002
some other command
$ history
1 13 aug 2013 10:44 some other command
2 13 aug 2013 12:13 some command
It is however reasonable to believe that a sorted history file is more effective (bash doesn't have to do any shuffling).
As for lookup Ctrl-R is often useful. For other things look at e.g. Commands For Manipulating The History, Event Designators, Some Miscellaneous Commands etc.
Best Answer
Find this in .bashrc:
# Make bash append rather than overwrite the history on disk
# shopt -s histappend
and uncomment the second line!