Skip to main content

Command-line history

Part of an ongoing series of essays tentatively entitled Don’t embarrass me, Don’t embarrass yourself: Notes on thinking in C and Unix.

Good Unix programmers (or perhaps all Unix users) regularly interact with the operating system through an interactive shell, through which you type commands. There are a variety of shells, but many Unices [1] ship with a default of bash, the Bourne-again shell [2]. One nice thing about bash, and most other shells, is that it keeps a history of the commands you’ve typed, so that you can see what you’ve done in the past and do it again [3].

A frequent use of history is to repeat the last command you just typed, or to do a quick variant of the last command you just typed. To execute the command you just typed, you need only write !!. For example, when I’m lazy and I’ve forgotten the appropriate flags for doing multiple copies, I often write something like the following.

$ lpr cnix-command-line-history.ps -P duerer 
$ !!
lpr cnix-command-line-history.ps -P duerer

That last line is the shell telling me what it substituted for me. Another use of !! is when you realize that you should have executed the prior command with different permissions.

$ install eni /usr/local/bin
install: cannot create regular file '/usr/local/bin/eni': Permission denied
$ /usr/bin/sudo !!
/usr/bin/sudo install eni /usr/local/bin

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for username: 

For those of you don’t know, sudo allows you to execute commands as the root user [5].

Sometimes we want to repeat an earlier command. Fortunately, bash history provides some nice mechanisms for that, too. If you follow the ! with one or more letters, bash repeats the most recent command that started with those letters.

$ pwd
/home/rebelsky/Web/musings
$ !l
lpr cnix-command-line-history.md -P duerer
$ ls
cnix-command-line-history.html
cnix-command-line-history.md 
cnix-command-line-history.ps
$ !l
ls
cnix-command-line-history.html
cnix-command-line-history.md 
cnix-command-line-history.ps
$ !lp
lpr cnix-command-line-history.md -P duerer

Of course, not all of us remember our recent commands, so the shell provides a convenient history command to tell you what you’ve been up to [6].

$ history | tail -8
  525  html2ps < cnix-command-line-history.html > cnix-command-line-history.ps
  526  lpr cnix-command-line-history.ps
  527  pwd
  528  ls -l
  529  vi cnix-command-line-history.md
  530  jobs
  531  history
  532  history | tail -8

As this suggests, your commands are numbered [7]. You can also use ! [8] notation to refer to commands by number.

$ !526
lpr cnix-command-line-history.ps

Finally, you can refer to the last element of the previous command using !$ [9]. Here’s a variant of one example in which I used !$.

$ !ht
html2ps < cnix-command-line-history.html > cnix-command-line-history.ps
-bash: cnix-command-line-history.ps: cannot overwrite existing file
$ rm !$
rm cnix-command-line-history.ps
$ !h
html2ps < cnix-command-line-history.html > cnix-command-line-history.ps

Is that all that you can do with the command-line history? Certainly not. If you mistype a letter (or more) in the previous command, you can do a quick substitution using the ^ symbol

$ lpr -p duerer cnix-command-line-history.ps
lpr: Error - unable to access "duerer" - No such file or directory
$ ^-p^-P
lpr -P duerer cnix-command-line-history.ps

In case you couldn’t tell, we write a caret, the text to replace, another caret, and the replacement.

All of these fun history commands were created in the early days of Unix, before we had fancy displays, or perhaps even displays at all [14].
Now we have much fancier displays [15] with addressable cursors and everything. And with the fancier displays come other ways of dealing with your history.

For many, the easiest way to browse and use your history is with the arrow keys. The up-arrow key brings you backwards in your history. If you’ve gone too far back, the down-arrow key brings you forward [17]. Once you’ve found a command you like, you can edit it with the arrow keys, the delete key, and, well, any character you’d like to type.

You can also search backwards through commands with Ctrl-r. I will admit that I rarely, if ever, use that facility.

In fact, although I regularly access history through the arrow keys, I most regularly use the old-fashioned bang commands. I’m fast with them, and they help me get the job done.

I’d recommend that you practice with the various approaches, and see which one works for you. Perhaps the most important thing is knowing that you have a history, and that you can use it [18].


Summary:

  • !! (bang bang) - repeat the last command
  • !$ (bang dollar or bang bucks) - the last part of the last command
  • !5 (bang five) - repeat command five

[1] I believe that the plural of Unix is Unices. You can form plurals in your own way. Strangely, the jargon file entry for Unix does not provide a plural.

[2] Stupid puns is a hallmark of Unix tools. One of the earlier shells was the Bourne shell (sh), so named because it was written by Stephen Bourne. An updated version of it therefore got this name.

[3] My software design students know that they should keep their code DRY, as in Don’t Repeat Yourself. However, it turns out that we often need to rerun commands, in different contexts

[4] In case you weren’t sure, !! is pronounced bang bang. Unix folks tend to prefer words of one syllable. Exclamation point exclamation point takes too long to say.

[5] Because sudo asks for a password, and that password can grant root authority, you should always type the full path to sudo. Unfortunately, too few sets of instructions acknowledge that principle.

[6] Note that if someone else accesses your account, it also tells them what you’ve been up to. For that reason, some people like to clear out their history regularly.

[7] Should I have written Just like your days, your commands are numbered?

[8] bang

[9] !$ is typically pronounced bang dollar, but I suppose that if we are conserving syllables, we should pronounce it bang buck.

[10] caret [11].

[11] Not carrot [12].

[12] Also not car rot, which seems to happen in climates where they regularly ice the roads.

[14] Yes, there was a time in which we interacted with computers through typewriter-like machines. It even happened during my lifetime.

[15] Insert obligatory joke about the curses we place upon these new displays [16].

[16] It’s okay if you didn’t get that joke. But if you did, could you let me know, even if you didn’t think it was funny?

[17] Strangely enough, the down-arrow doesn’t work when it’s the first key you type. It appears that you cannot look into your command future.

[18] Or is that two things?


Version 1.0 of 2017-01-16.