If you’ve worked in the terminal, it’s likely you’re in some way proficient with the command history features of your shell. There’s a lot more functionality than many realise however, and by learning it you can eliminate a lot of duplicate typing.

The first thing most people learn about the command history is that you can go back and forward through your history with the up and down keys. Bash stores history entries between shells by default (on most distributions), so you should have access to the commands you typed previously, regardless of which terminal you’re currently working in. You can turn this behaviour off, so that history works only for the current invocation of the shell you’re using by adding the following line to one of your start-up files (say, ~/.bashrc):

SAVEHIST=0

The amount of commands stored in the history file is dependent on the size of the file you allocate. By default 500 commands are stored, but you can tweak these values by setting the following options in a startup file:

HISTSIZE = 1000
HISTFILE = ~/.bash_history

To print out the entire history file, you can use the history command:

$ history | tail -10
 522 gvim
 523 vim .bashrc 
 524 vim .bash_profile 
 525 history
 526 ls
 527 echo $SHELL
 528 echo $HISTFILE
 529 echo $HISTSIZE
 530 vim .bashrc 
 531 history | tail -10
$

The number in the left column is the history item number. This can be bigger than the size of your stored history file, as commands from the current shell are not added to the file until the shell is closed.

You can jump straight to executing any line in your history by typing an ‘!’ followed by the item number. So for example if we wanted to echo the shell name to the console again we could write echo $SHELL or simply:

$ !527
/bin/bash
$

Searching command history

You can also use the ! command to search through the history, by replacing the item number with characters from the start of the command. The previous example can now just as easily be written:

$ !echo
echo $SHELL
/bin/bash
$

Often this becomes unwieldy since you have to match the command from the beginning, and many commands start in the same way (eg. “echo $HISTFILE”, “echo $HISTSIZE”, “echo $SHELL”). You can always hack something together using history and grep, but there’s an easier way with the ‘!?’ command. ‘!?’ followed by a simple string, executes the last command in the history that contains that string.

So, to reprint the name of the shell we could have simply typed:

$ !? SHELL
/bin/bash
#

More usefully, you can interactively search the command history at the console by hitting CTRL-R at the prompt and typing the section of the string you are looking for. You can only use CTRL-R interactively, that is, not in a script (although relying on the history in a script can be dangerous anyway), but it can save you more keystrokes as it displays the match at each point, meaning you can stop searching once you’ve found it.

The previous example using CTRL-R interactive search:

(reverse-i-search)`SH': echo $SHELL

$HISTIGNORE

The HISTIGNORE environment variable controls which commands are entered into the history and which are ignored. It contains a list of patterns separated by colons (‘:’) that when matched, drops a command rather than includes it in the file. So for example, if you don’t need to see the ‘history’ program in the command history (since it’s fairly redundant), you could do the following:

$ export HISTIGNORE="history"
$ history
...
$ history | tail -1
581 export HISTIGNORE="history"
582 history | tail -1

You can see here that the line with simply history on it has not been added to the list, while the history | tail -1 has — only exact matches in the HISTIGNORE list are filtered out. If you don’t want any lines beginning with history to be in the command history you can amend your HISTIGNORE variable to:

$ export HISTIGNORE="history*"

Be warned however than ignoring an item from the history means that it cannot be recalled by any means — not even with the up and down arrows. If you still wish to keep this behaviour for all commands, but not have them show up in a history file, you may be better served by leaving HISTIGNORE alone and trimming the file with a script on logout.

Some people use this variable to keep their history file nice and tidy, by removing the commands that they’re unlikely to bother recalling, such as ls, fg or exit. Another good tip comes from this page which includes the tip that if you add "[ \t]*" to your HISTIGNORE variable you can make any command be ignored by starting it with a space. Good if you need a little extra privacy for some commands.

Subscribe to the Developer Insider Newsletter

From the hottest programming languages to commentary on the Linux OS, get the developer and open source news and tips you need to know. Delivered Tuesdays and Thursdays

Subscribe to the Developer Insider Newsletter

From the hottest programming languages to commentary on the Linux OS, get the developer and open source news and tips you need to know. Delivered Tuesdays and Thursdays