Basics of the Linux Bash Command History with Examples



The bash command history shows the previously used commands. By default, the history is saved in memory per session and can be saved to a file for later sessions. We will explore ways to show, search and modify the history in this blog post.

I use RHEL and Debian-based Linux distributions and bash in this blog post as a reference.

Configuration #

I want to start with ways to configure the behavior of the bash history.

The configuration of the history can be changed in the bash startup file. Those can typically be found in the home directory of the user.

System-wide /etc/profile or in the home directory ~/.bashrc or ~/.profile. There are more, but just to list some examples.

If you want to use an option for one session only, you can just type it in like this:

HISTFILE=/dev/null or unset HISTFILE

In both ways, you would disable the history for the current bash session.

The basics #

The bash history should be enabled by default, but you might want to change some settings.

The history file that is stored on disk can be found with the following command:

The default location for the history on disk is ~/.bash_history.

Add the following option to change the name and storage location of the history file on disk:
Show the complete history from memory:
Just show the last number of commands:
history 20
Read history from disk to memory:
history -r
Append history entries from memory to disk:
history -a
Overwrite the disk history with the memory history:
history -w

Since I am used to working with multiple sessions and I want to share the history of them, I’ve added the following line to my startup file to append every entry to the history on disk.

export PROMPT_COMMAND='history -a'

Delete a specific history entry or range:
history -d 20 # one specific entry
history -d 15-20 # range
history -d -5 # last ‘n’ of entries

Disabling bash command history #

As mentioned above, there are multiple options to disable the bash command history.

HISTFILE=/dev/null or unset HISTFILE

Number of history entries

The following option sets the number of entries that are displayed if you enter history:
The following option sets the maximum number of entries in the history on disk:

Search function #

You can start a reversed search through the history by pressing CTRL + r and entering the search term. You can jump to the next result by pressing CTRL + r again. After finding the desired command, you can press TAB to get filled to the current command line or press ENTER to run the command immediately.

If you skipped through your desired command, you can cancel the current search request with CTRL + g and start from the top again.

There is no native way to jump forward again - but you could add a forward search by adding stty -ixon to your startup file. The keyboard shortcut for the forward search is CTRL + s.

Using ‘grep’

I prefer to use grep to find commands. Simply use one of these examples to do so.

history | grep SEARCHTERM

Side note: use the -i flag if you want search case-insentitive.

Add comments to commands

You can add comments to commands with #. This makes it easy to find commands again or document the thoughts behind the command in troubleshooting sessions and later reviews.

kuser@pleasejustwork:$ echo nightmare # dolphins chasing me in a mall

Exclusions #

We can add exclusion with the HISTIGNORE option in your startup file. This can be useful for privacy and security reasons.

There are some predefined options we can choose from:
ignorespaces - if the command starts with a SPACE, it will be excluded
ignoredups - duplicate commands will be excluded
ignoreboth - both above-mentioned options together

If those options are not enough, you can create your own rules. For example, the ignoreboth rule could be written like this:

HISTIGNORE="&:[ ]*" # the ampersand & means no duplicates, : is the separator, [ ]* checks if the command begins with a SPACE

You can add commands too.


Timestamps #

Timestamps are often important for reviews of troubleshooting sessions. With the HISTTIMEFORMAT option, you can add timestamps in various formats to your history.

The default history looks like this:

kuser@pleasejustwork:$ history 6
 1150  history
 1151  vim .bash_history 
 1152  vim .bashrc 
 1153  source .bashrc
 1154  ls
 1155  history

And the same lines look like this after adding HISTTIMEFORMAT="%F %T " to the configuration:

kuser@pleasejustwork:$ history 6
 1150  02/02/23 18:03:32 history
 1151  02/02/23 18:03:45 vim .bash_history 
 1152  02/02/23 18:05:03 vim .bashrc 
 1153  02/02/23 18:05:22 source .bashrc
 1154  02/02/23 18:05:26 ls
 1155  02/02/23 18:05:30 history

You can adjust the format with the following placeholders:

    %d: day
    %m: month
    %y: year
    %H: hour
    %M: minutes
    %S: seconds
    %F: full date (Y-M-D format)
    %T: time (H:M:S format)
    %c: complete date and timestamp (day-D-M-Y H:M:S format)

Re-run commands #

!! is a variable for the previous command and, for example, can be used to run the last command as ‘sudo’ .

kuser@pleasejustwork:$ whoami
kuser@pleasejustwork:$ sudo !!
[sudo] password for kuser: 

! can be used to re-run the last command starting with a chosen term.

kuser@pleasejustwork:$ history 5
   41  ping         # !ping
   42  whoami                    # !whoami
   43  nmap -sP    # !nmap
   44  vim .bashrc               # !vim
   45  history
kuser@pleasejustwork:$ !who      # runs immediately and auto-completes

!n would run the ‘n’ command in the history, and !-n refers to the current command minus ‘n’

kuser@pleasejustwork:$ history 5
   41  ping         # !41 / !-5
   42  whoami                    # !42 / !-4
   43  nmap -sP    # !43 / !-3
   44  vim .bashrc               # !44 / !-2
   45  history                   # !45 / !-1 / !!
kuser@pleasejustwork:$ !-4       # runs immediately

modify and re-run previous command

With the following syntax, you can replace keywords from the previous command and run it again.



kuser@pleasejustwork:$ sudo nmap -T3 -p 80,443
kuser@pleasejustwork:$ ^22^50^            # the command will be executed immediately
kuser@pleasejustwork:$ sudo nmap -T3 -p 80,443`

Use a backslash \ as an escape character if you need to find or replace a ^.