What's the difference between "history -w" and the action of closing a shell session?

I did some tests about history:

  1. I ran history-c and then logged out. This cleared history for the current shell.

  2. I ran history -c && history -w. This deleted everything.

  3. I deleted the entire contents of the history file by vi editor: $vi ~/.bash_history. And then I logged out. In the next login, when I ran history only the lines or commands of last shell session is there.

This shows that there are differences between history -w and the action when we close a shell session.

What really happens when we close a shell session?

I think history -w overwrites memory contents to history file, and history -c deletes memory contents. Is this correct?


Solution 1:

When dealing with Bash history, we have two kinds:

  1. a history list in memory
  2. the .bash_history file on disk

When Bash starts (assuming a default configuration), it will load the contents of your .bash_history file into the history list in memory (after truncating it to the configured size, if necessary).

Then you type your commands which get appended to the history list in memory only. The history file on your disk does not get touched.

Exiting your Bash session regularly (not forcefully killing it or causing it to crash somehow) by default truncates your history list in memory to fit the configured maximum size and then appends only new entries from the current Bash session (because by default the histappend option is enabled) to your history file on the disk, without deleting removed entries or re-adding content from previous sessions.


When you run history -c you clear the complete history list in memory, but again this does not affect the history file on the disk.

Running history -w writes your current history list in memory to the history file on disk. It does not append new entries but overwrites the complete file. Therefore running history -c && history -w effectively clears the history file as well.


Manually clearing your history file by editing it from within a running Bash session has not the expected effect or permanently deleting the entire history so far, because the history list in memory which still contains all old entries from the history file will stay intact.

On exiting your Bash session, the history file will get rewritten with the data from the history list. However, as by default the histappend option is enabled, only new entries from the current Bash session will be written to the file, older history data gets discarded. You would have to run history -w to save the full history list to disk.


What exactly happens when a Bash shell starts and exits can be read in man bash:

HISTORY
       When the -o history option to the set builtin  is  enabled,  the  shell
       provides access to the command history, the list of commands previously
       typed.  The value of the HISTSIZE variable is used  as  the  number  of
       commands to save in a history list.  The text of the last HISTSIZE com‐
       mands (default 500) is saved.  The shell stores  each  command  in  the
       history  list  prior to parameter and variable expansion (see EXPANSION
       above) but after history expansion is performed, subject to the  values
       of the shell variables HISTIGNORE and HISTCONTROL.

       On startup, the history is initialized from the file named by the vari‐
       able HISTFILE (default ~/.bash_history).  The file named by  the  value
       of  HISTFILE  is  truncated,  if necessary, to contain no more than the
       number of lines specified by the value of HISTFILESIZE.   If  HISTFILE‐
       SIZE  is unset, or set to null, a non-numeric value, or a numeric value
       less than zero, the history file is not truncated.   When  the  history
       file  is  read, lines beginning with the history comment character fol‐
       lowed immediately by a digit are interpreted as timestamps for the pre‐
       ceding history line.  These timestamps are optionally displayed depend‐
       ing on the value of the HISTTIMEFORMAT variable.   When  a  shell  with
       history  enabled  exits,  the  last $HISTSIZE lines are copied from the
       history list to $HISTFILE.  If the histappend shell option  is  enabled
       (see  the description of shopt under SHELL BUILTIN COMMANDS below), the
       lines are appended to the history file, otherwise the history  file  is
       overwritten.   If  HISTFILE  is  unset,  or  if  the  history  file  is
       unwritable, the history is not saved.  If the  HISTTIMEFORMAT  variable
       is  set,  time  stamps are written to the history file, marked with the
       history comment character, so they may be preserved across  shell  ses‐
       sions.   This  uses  the history comment character to distinguish time‐
       stamps from other history lines.  After saving the history, the history
       file is truncated to contain no more than HISTFILESIZE lines.  If HIST‐
       FILESIZE is unset, or set to null, a non-numeric value,  or  a  numeric
       value less than zero, the history file is not truncated.