Using Bash's History Effectively

I will attempt here to focus on only one feature of Bash, its command history. There are other good documents on the other features of Bash. If you're interested in anything other than the command history/recall, then this document really isn't going to fulfill your needs.

Okay, so let's get into it!

What is Bash? "Descended from the Bourne Shell, Bash is a GNU product, the "Bourne Again SHell." It's the standard command line interface on most Linux machines. It excels at interactivity, supporting command line editing, completion, and recall." --Bash Prompt HOWTO

So, Bash is GNU software and all that that implies (GPL, free, reliable, etc.). It's the de facto standard interface that you use to interact with the system from a command line. Bash is also highly configurable. We're going to take advantage of that later...

The last feature mentioned as one of the major selling points of Bash is "recall". This is what I've been calling the command history. When typing commands at the command line interface (CLI), one can sometimes come up with rather long commands.

While completion (feature #2) alleviates much of the pain associated with entering long commands and deserves an entire presentation unto itself (stay tuned), completion also adds to the problem in a way, by making longer commands more acceptable. If we didn't have completion, we might not name our files "really_big_file.txt.old.do_not_delete_yet".

There's also the advent of long options, prevalent in the GNU world. So, instead of netstat -rn you might have netstat --route --numeric.

Then, of course, there's always the endless stringing together of commands with pipes (|) to make mini programs (my personal favorite).

So, we have this problem where command lines can get very long. Well, it's one thing to build up long commands once. The frustration comes in having to build them up repeatedly. The obvious solution is to store commands entered on the command line and provide access to those stored commands so that they can be used again with relative ease.

That is Bash's history/recall function in a nutshell. You just press the up arrow to scroll back through your command history. See the command you want and press Enter/Return to execute it again.

Now if that were all there was to command history, it would be pretty weak. Naturally, one might want to improve upon a previous command and Bash uses GNU Readline to provide full editing capabilities at the command-line. So, say you have a command like this:

Then you realize that you meant to do a case-insensitive grep, so you hit the up arrow and recall the command. Your cursor is sitting at the end of the line. All you have to do is arrow back four times (or just type meta-b) and type "-i ":

A total of 5 keystrokes, not including the added text and pressing Enter, both of which you would've had to do anyway. Using Readline's meta-b shortcut saves another two keystrokes... truly efficient.

Okay, well say you didn't just run the sought-after command. You know you've used it within the past few days, but you don't want to scroll through what could be hundreds of commands to find it. Well, there are a couple of ways to do this, depending on how much you can remember about the history yourself...

Remember:  Once you've used one of these methods to recall and execute a command, that command is now the most recent command in your history. You can now just press the up arrow once to retrieve it again.

Okay, so now you can recall commands with relative ease. But we really haven't done anything special yet. We're just using the default behaviors and commands provided in Bash. The trick comes in configuring what gets put into your history!

A little-known trick (I've only seen one distro ship with this turned on by default) is that you can filter what gets stored in the command history. This is done merely by setting an environment variable, $HISTIGNORE.

Just set the HISTIGNORE variable to a colon-delimited list of patterns which should be excluded. There's also the special pattern '&', which suppresses duplicate entries (very useful!).

Here's an example that suppresses duplicate commands, the simple invocation of 'ls' without any arguments, and the shell built-ins bg, fg, and exit:

Try it out. I think you'll like it.

Here's a neat trick, submitted by Robert Cymbala. If you include the expression "[ \t]*" in the HISTIGNORE string, you can suppress history recording at will for any given command just by starting with a space!

Another optional feature of Bash history filtering that isn't always enabled by default in distributions is cmdhist. This determines whether multi-line commands are stored in the history as a single command (on) or not (off; default). This makes it much easier to go back and edit multi-line commands.

To enable this feature, you would type

To disable this feature, you would type

As you may have guessed, there are many options for Bash that can be toggled using the 'shopt' built-in. They are documented here.

There exist many more interesting things that can be done with Bash's command history. I refer those interested in further details to the official Bash Reference at the GNU website. For more on the various special shell variables used by Bash, see this page and (search for "HIST").

I hope this has been an approachable and useful tour of Bash's command history feature.

Jason Bechtel <jason m bechtel a@t gmail d.o.t com>

(last updated 12/19/2007)