arturomp
arturomp

Reputation: 29620

bash (or zsh) HISTSIZE vs. HISTFILESIZE?

What is the difference in HISTSIZE vs. HISTFILESIZE?

They are used to extend bash history beyond the default 500 lines.

There seems to be a lack of clarity here and in other forums about why they are both needed. (Example 1, Example 2, Example 3).

Is this the same for zsh?

Upvotes: 248

Views: 98083

Answers (3)

user3443139
user3443139

Reputation: 802

BASH Manual: Bash Variables

BASH Manual: Bash History Facilities

To preserve the Bash historic history data on disk the shell option histappend must be set, otherwise the disk history file is simply overwritten!

shopt -s histappend

HISTFILESIZE
If the value is 0, the history file is truncated to zero size.
Non-numeric values and numeric values less than zero inhibit truncation.

HISTSIZE
If the value is 0, commands are not saved in the history list.
Numeric values less than zero result in every command being saved on the history list (there is no limit).

I'd recommend Connor's settings (shown below in an example .bashrc file).

HISTCONTROL is another interesting setting for removing duplicates ('dups'); and/or not storing commands in the history if they start with a space character are not saved in the history (privacy option).

HISTTIMEFORMAT records a timestamp with each history command. It's display format is customizable. It saves seconds since the epoch in the history file.

$ cat .bashrc
# ignoreboth : don't put duplicate lines or lines starting with space in the history.
# ignoredups : don't put duplicate lines in the history.
# erasedups  : causes all previous lines matching the current line to be removed
#              from the history list before that line is saved
HISTCONTROL=ignoredups

# append to the history file, don't overwrite it
shopt -s histappend

HISTSIZE=infinity
HISTFILESIZE=andbeyond

HISTTIMEFORMAT="%F %T: "
$ tail .bash_history
#1737278025
history
#1737278034
more ~/.bash_history
#1737278039
tail ~/.bash_history
#1737279248
history
#1737279256
more .bash_history
$ date --utc --date="@1737279256"
Sun Jan 19 09:34:16 AM UTC 2025
$ history 5
 2652  2025-01-19 09:41:07: ls -ltr
 2653  2025-01-19 09:41:09: cat .bashrc
 2654  2025-01-19 09:41:11: history 5
 2655  2025-01-19 09:41:22: date --utc --date="@1737279256"
 2656  2025-01-19 09:41:24: history 5

Upvotes: 0

arturomp
arturomp

Reputation: 29620

Short answer:

HISTSIZE is the number of lines or commands that are stored in memory in a history list while your bash session is ongoing.

HISTFILESIZE is the number of lines or commands that (a) are allowed in the history file at startup time of a session, and (b) are stored in the history file at the end of your bash session for use in future sessions.

Notice the distinction between file: on disk - and list: in memory.

(NOTE: as noted by this, in zsh HISTFILESIZE should be SAVEHIST)

Long answer:

All the info above + some examples:

Example 1: HISTFILESIZE=10 and HISTSIZE=10

  1. You start your session.
  2. Your HISTFILE (file that stores your bash command history), is truncated to contain HISTFILESIZE=10 lines.
  3. You write 50 lines.
  4. At the end of your 50 commands, only commands 41 to 50 are in your history list, whose size is determined by HISTSIZE=10.
  5. You end your session.
  6. Assuming histappend is not enabled, commands 41 to 50 are saved to your HISTFILE which now has the 10 commands it held at the beginning plus the 10 newly written commands.
  7. Your HISTFILE is truncated to contain HISTFILESIZE=10 lines.
  8. You now have 10 commands in your history - the last 10 that you just typed in the session you just finished.
  9. When you start a new session, you start over at step 1 with a HISTFILE of HISTFILESIZE=10.

Example 2: HISTFILESIZE=10 and HISTSIZE=5

  1. You start your session.
  2. Your HISTFILE (file that stores your bash command history), is truncated to contain at most HISTFILESIZE=10 lines.
  3. You write 50 lines.
  4. At the end of your 50 commands, only commands 46 to 50 are in your history list, whose size is determined by HISTSIZE=5.
  5. You end your session.
  6. Assuming histappend is not enabled, commands 46 to 50 are saved to your HISTFILE which now has the 10 commands it held at the beginning plus the 5 newly written commands.
  7. Your HISTFILE is truncated to contain HISTFILESIZE=10 lines.
  8. You now have 10 commands in your history - 5 from a previous session and the last 5 that you just typed in the session you just finished.
  9. When you start a new session, you start over at step 1 with a HISTFILE of HISTFILESIZE=10.

Example 3: HISTFILESIZE=5 and HISTSIZE=10

  1. You start your session.
  2. Your HISTFILE (file that stores your bash command history), is truncated to contain at most HISTFILESIZE=5 lines.
  3. You write 50 lines.
  4. At the end of your 50 commands, only commands 41 to 50 are in your history list, whose size is determined by HISTSIZE=10.
  5. You end your session.
  6. Assuming histappend is not enabled, commands 41 to 50 are saved to your HISTFILE which now has the 5 commands it held at the beginning plus the 10 newly written commands.
  7. Your HISTFILE is truncated to contain HISTFILESIZE=5 lines.
  8. You now have 5 commands in your history - the last 5 that you just typed in the session you just finished.
  9. When you start a new session, you start over at step 1 with a HISTFILE of HISTFILESIZE=5.

Info from elixir_sinari:

The history "file" is not updated as you type the commands. The commands get stored in a "list" separately (accessed by the history command). The number of these stored commands is controlled by HISTSIZE value. When the shell (interactive) exits, the last $HISTSIZE lines are copied/appended to $HISTFILE from that "list". If HISTFILESIZE is set, then after this operation, it is ensured that only $HISTFILESIZE lines (latest) exist in $HISTFILE . And when the shell starts, the "list" is initialized from $HISTFILE up to a maximum of $HISTSIZE commands.

And from the man bash page:

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 commands (default 500) is saved. (...)

On startup, the history is initialized from the file named by the variable 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. (...) When an interactive shell 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. (...) After saving the history, the history file is truncated to contain no more than HISTFILESIZE lines. If HISTFILESIZE is not set, no truncation is performed.

Upvotes: 406

Pithikos
Pithikos

Reputation: 20310

Building on top of what arturomp have said and in an effort to make it a bit clearer.

Assumming you have 2000-something long history..

~$ history
    1  sdf
    2  fghdfgjf
    3  fghfghdf
   ..  ..
 2027  78
 2028  57
 2029  yu45u

You can cut down what you are shown with HISTSIZE

~$ HISTSIZE=5
~$ history
 2026  546
 2027  78
 2028  56
 2029  yu45u
 2030  HISTSIZE=5

Now, no matter how many commands you type, only the last 5 will be recorded.

~$ ABC
~$ GGH
~$ GSDHFG
~$ JFDR
~$ ABSDDS
~$ AHFGHFD
<close terminal>
<open new terminal>
~$ history
    1  sdf
    2  fghdfgjf
    3  fghfghdf
   ..  ..
 2028  56
 2029  yu45u
 2030  HISTSIZE=5
 2031  GGH
 2032  GSDHFG
 2033  JFDR
 2034  ABSDDS
 2035  AHFGHFD

We can clearly see that our first command ("ABC") is not in the history since only the last 5 commands were recorded.

Now, the total history is stored in a file (.bash_history) and you can alter how long this file gets with the HISTFILESIZE. For example with a 2033 HISTFILESIZE, in my case I would have this:

~$ history
    1  fghfghdf
    2  gegege
    3  gege
   ..  ..
 2028  HISTSIZE=5
 2029  GGH
 2030  GSDHFG
 2031  JFDR
 2032  ABSDDS
 2033  AHFGHFD

Upvotes: 8

Related Questions