Under Construction

Controlling which Commands are added to the History

The bash allows to configure which commands are to be included in the history list and which not. There are two bash variables HISTCONTROL and HISTIGNORE for this purpose. The options for both variables are briefly presented below.

One and the same command is often executed several times in a row, e.g.:

[user01@aixe01 ~]$ date
Fri Apr 29 20:18:52 CEST 2022
[user01@aixe01 ~]$ date
Fri Apr 29 20:18:57 CEST 2022
[user01@aixe01 ~]$

By default, all commands are included in the history list, which means that in the case above, the same command appears twice in a row in the history:

[user01@aixe01 ~]$ history
    1  ls -l
    2  ls -l
    3  hostname
    4  df /
    5  pwd
    6  date
    7  date
    8  history
[user01@aixe01 ~]$

By setting the variable HISTCONTROL to the value ignoredups, identical commands executed several times in succession are only added once to the history list:

[user01@aixe01 ~]$ HISTCONTROL=ignoredups
[user01@aixe01 ~]$

If you now execute the date command twice in succession, as above:

[user01@aixe01 ~]$ date
Fri Apr 29 20:30:03 CEST 2022
[user01@aixe01 ~]$ date
Fri Apr 29 20:30:05 CEST 2022
[user01@aixe01 ~]$

the date command is recorded only once in the history:

[user01@aixe01 ~]$ history
    1  ls -l
    2  ls -l
    3  hostname
    4  df /
    5  pwd
    6  date
    7  date
    8  history
    9  HISTCONTROL=ignoredups
   10  date
   11  history
[user01@aixe01 ~]$

After setting HISTCONTROL, date was only recorded once as command with number 10 in the history list. However, the two previous occurrences of date (command 6 and command 7) remain in the history list.

In the history list above, the date command appears a total of three times, and the history command twice. If you only want a command to be recorded once in the history list, you can set the variable HISTCONTROL to the value erasedups:

[user01@aixe01 ~]$ HISTCONTROL=erasedups
[user01@aixe01 ~]$   

When a command is added to the history list, previous occurrences of that command are removed. We run the date command twice in succession again:

[user01@aixe01 ~]$ date
Fri Apr 29 20:33:44 CEST 2022
[user01@aixe01 ~]$ date
Fri Apr 29 20:33:46 CEST 2022
[user01@aixe01 ~]$

Listing the history list shows that the date command now only occurs once:

[user01@aixe01 ~]$ history
    1  ls -l
    2  ls -l
    3  hostname
    4  df /
    5  pwd
    6  HISTCONTROL=ignoredups
    7  HISTCONTROL=erasedups
    8  date
    9  history
[user01@eaixe01 ~]$

The multiple occurrences of the history command have also been removed and only the last history command is found in the history list! However, the “ls -l” command is still found twice at the beginning of the history list. The duplicates are only removed when adding a command to the history list! We execute “ls –l” once and then the history command:

[user01@aixe01 ~]$ ls -l
total 29128
drwxr-xr-x    2 user01  staff         12288 Apr 29 14:01 bin/
drwxr-xr-x    2 user01  staff           256 Apr 29 10:59 etc/
...
-rw-r--r--    1 user01  staff            21 Apr 14 11:13 sample.txt
[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
[user01@aixe01 ~]$

You can see that the two occurrences of “ls -l” at the beginning of the history list have been removed and the command is now the penultimate command in the list.

Whether you prefer erasedups or ignoredups is of course very subjective. Ultimately, each user has to decide this for themselves. We prefer the ignoredups setting.

The HISTCONTROL variable allows a third value, namely ignorespace. This setting gives the user control of whether or not a command should be included in the history list or not, for each individual command. We first set the value of HISTCONTROL to ignorespace:

[user01@aixe01 ~]$ HISTCONTROL=ignorespace
[user01@aixe01 ~]$

If a space is entered in front of a command, the command is not included in the history list. If no space is placed in front, the command is included in the history list as usual. We first start the date command without a leading space and then the hostname command with one or more spaces in front of the command:

[user01@aixe01 ~]$ date
Fri Apr 29 20:50:55 CEST 2022
[user01@aixe01 ~]$    hostname
aixe01
[user01@aixe01 ~]$

Printing the history list shows that the hostname command has not been included in the history list, unlike the date command:

[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
    9  HISTCONTROL=ignorespace
   10  date
   11  history
[user01@aixe01 ~]$

If you want to use ignoredups (from above) and ignorespace together, you can specify both values separated by a colon “:“:

[user01@aixe01 ~]$ HISTCONTROL=ignoredups:ignorespace
[user01@aixe01 ~]$

We execute again twice the date command (without leading spaces), followed by the hostname command with leading space(s):

[user01@aixe01 ~]$ date
Fri Apr 29 20:58:32 CEST 2022
[user01@aixe01 ~]$ date
Fri Apr 29 20:58:34 CEST 2022
[user01@aixe01 ~]$    hostname
aixe01
[user01@aixe01 ~]$

This has the desired effect:

[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
    9  HISTCONTROL=ignorespace
   10  date
   11  history
   12  HISTCONTROL=ignoredups:ignorespace
   13  date
   14  history
[user01@aixe01 ~]$

Note: Instead of “ignoredups:ignorespace” you can also use “ignoreboth“!

Note: If you want to combine erasedups with ignorespace, there is no shortcut. You must then specify both values separated by a colon “:“, e.g. “erasedups:ignorespace“.

We enter our favorite “ignoreboth” in the startup file ~/.bashrc:

[user01@aixe01 ~]$ cat ~/.bashrc

HISTCONTROL=ignoreboth

[user01@aixe01 ~]$

Another way to control which commands are included in the history list is via the HISTIGNORE variable. A colon-separated list of patterns can be specified as the value. If an entered command matches one of the patterns, it will not be included in the history list. A pattern must match the complete command line.

We demonstrate this using the history command as an example. We don’t want it to be included in the history list:

[user01@aixe01 ~]$ HISTIGNORE=history
[user01@aixe01 ~]$

First we start a date command again:

[user01@aixe01 ~]$ date
Fri Apr 29 21:11:03 CEST 2022
[user01@aixe01 ~]$

Then we print the history list with the history command. The history command should no longer appear at the end of the history list:

[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
    9  HISTCONTROL=ignorespace
   10  date
   11  history
   12  HISTCONTROL=ignoreboth
   13  date
   14  history
   15  HISTIGNORE=history
   16  date
[user01@aixe01 ~]$

As expected, date is the last command in the history list! However, if you specify history followed by a space:

[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
    9  HISTCONTROL=ignorespace
   10  date
   11  history
   12  HISTCONTROL=ignoreboth
   13  date
   14  history
   15  HISTIGNORE=history
   16  date
   17  history
[user01@aixe01 ~]$

then history is again listed as the last command. This is because the entire command line, here including the space at the end, must always match the pattern(s). One could use “history*” as a pattern, which would exclude history followed by zero, one or more arbitrary characters from the history list:

[user01@aixe01 ~]$ HISTIGNORE='history*'
[user01@aixe01 ~]$

If you type history again followed by a space:

[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
    9  HISTCONTROL=ignorespace
   10  date
   11  history
   12  HISTCONTROL=ignoreboth
   13  date
   14  history
   15  HISTIGNORE=history
   16  date
   17  history
   18  HISTIGNORE='history*'
[user01@aixe01 ~]$

history will no longer be appended to the end of the history list this time.

If there is a command that starts with history, e.g. “historyNew“:

[user01@aixe01 ~]$ echo "echo new history" >historyNew
[user01@aixe01 ~]$ chmod a+x historyNew
[user01@aixe01 ~]$

Then the execution of this command is not entered in the history list:

[user01@aixe01 ~]$ historyNew
new history
[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
    9  HISTCONTROL=ignorespace
   10  date
   11  history
   12  HISTCONTROL=ignoreboth
   13  date
   14  history
   15  HISTIGNORE=history
   16  date
   17  history
   18  HISTIGNORE='history*'
   19  echo "echo new history" >historyNew
   20  chmod a+x historyNew
[user01@aixe01 ~]$

We therefore change the HISTIGNORE variable as follows:

[user01@aixe01 ~]$ HISTIGNORE='history:history *'
[user01@aixe01 ~]$

If you now enter the history command (without a space at the end) or history followed by a space and then no, one or more characters, this will not be recorded in the history list. However, historyNew now no longer matches and is correctly included in the history list:

[user01@aixe01 ~]$ historyNew
new history
[user01@aixe01 ~]$ history
    1  hostname
    2  df /
    3  pwd
    4  HISTCONTROL=ignoredups
    5  HISTCONTROL=erasedups
    6  date
    7  ls -l
    8  history
    9  HISTCONTROL=ignorespace
   10  date
   11  history
   12  HISTCONTROL=ignoreboth
   13  date
   14  history
   15  HISTIGNORE=history
   16  date
   17  history
   18  HISTIGNORE='history*'
   19  echo "echo new history" >historyNew
   20  chmod a+x historyNew
   21  HISTIGNORE='history:history *'
   22  historyNew
[user01@aixe01 ~]$

This can be used to prevent arbitrary commands from being included in the history list.

The patterns to be excluded should again be configured via one of the bash startup files. As usual, we use ~/.bashrc:

[user01@aixe01 ~]$ cat ~/.bashrc

HISTIGNORE='history:history *'

[user01@aixe01 ~]$

When checking whether a command should be included in the history list, the variable HISTCONTROL is used first, only then are the patterns from HISTIGNORE checked.