Just about anyone who works on the command line of a Unix/Linux systems knows about history. Having the ability to repeat their most recent command by just typing !! or the most recent command that starts with a particular letter by typing something like !s saves them a lot of typing and a lot of typos. But these uses of the history feature of the shell only scratch the surface of what it can do for you.
You can also edit prior commands, find prior commands based on particular substrings, determine how much history is preserved for you, remove commands from your history, filter (omit) commands so they're never save in your history, and clear your history altogether.
How does the history command work? It stores the commands that you type in a history buffer that isn't written to your history file -- which might be .history or .bash_history -- until you log out. When you type history on the command line, what you see will be a combination of the commands you've typed since you started your current shell and earlier commands that were recorded in your history file.
If you start a second shell by typing /bin/bash, enter some commands, exit that shell, and type some additional commands, the commands that you entered in the subshell will appear in your history file prior to those you entered before starting the shell because that shell exited first. Try this:
$ echo 1 1 $ echo 2 2 $ echo 3 3 $ /bin/bash $ echo 4 4 echo 5 5 $ exit $ history 5 42 echo 1 43 echo 2 44 echo 3 45 /bin/bash 46 history 5
Log off and back in and then:
$ tail .bash_history history /bin/bash echo 4 echo 5 echo 1 echo 2 echo 3 /bin/bash history 5 tail -5 .bash_history
Notice how the echoes of 1, 2 and 3 appear after 4 and 5 even though you entered those commands earlier.
Any time you start a new shell, you will see only the commands you have typed since invoking it and commands that were previously stored in your history file. Run this script and it will not see any of the commands you typed just before running it.
#!/bin/bash whoami history 10
Run this one and it will -- because this one doesn't spawn a new shell.
whoami history 10
You can see a portion of your history by using an argument with the history command. For example, history 5 shows you only the most recent 5 commands. You can selectively remove commands from your history file using history -d:
$ history 6 42 echo 1 43 echo 2 44 echo 3 45 echo 4 46 echo 5 47 history 6 $ history -d 45 $ history 6 43 echo 2 44 echo 3 45 echo 5 46 history 6 47 history -d 45 48 history 6
The -d option is particularly handy if you completely botched a command and want to be sure not to repeat the mistake when you re-use commands.
You can clear your history buffer with the -c argument, though the old entries in your history file will remain intact until you log off.
$ history -c
You can also modify commands and run them again by using the ^old^new^ syntax.
$ cal 10 2012 October 2012 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 $ ^0^1^ cal 11 2012 November 2012 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Typing ^r (control-r) allows you to search your history for particular strings regardless of where the strings appear within your prior commands -- thus more flexible than the !l syntax. You might want to locate and re-run the last command you ran against a particular file or using a particular filter. Type ^r and you will see this prompt asking you for your search term:
How much history you preserve depends on your HISTSIZE setting. Generally set to 1000 commands, this allows you to reach back pretty far into your command history. If you don't want these lines to preserve all of your ls, pwd, bg, fg, history and exit commands, you can exclude these commands by setting your HISTIGNORE. Just remember to add a line like this to your .bash_profile.
If you are staring at that heading and asking yourself "shopt? what's that?", you're not alone. This command isn't in the most likely Unix commands to be used. In fact, it's not really a command, but a shell built-in. So you won't find it using the which command, but the man page should provide a lot of good information. The word "shopt" doesn't suggest its use if you, like me, see "shop tee". If you can think of it instead as "sh opt" (shell options), it will be a little easier to remember. The shopt built-in allows you to toggle settings that control shell behavior, some of which affect how the history command behaves.
In the shopt output below, you can see whether various features of the shell are turned on or off. With an s (set) argument, shopt turns a feature on while with a u (unset) argument, it turns them off.
$ shopt cdable_vars off cdspell off checkhash off checkwinsize on cmdhist on dotglob off execfail off expand_aliases on extdebug off extglob off extquote on failglob off force_fignore on gnu_errfmt off histappend off histreedit off histverify off hostcomplete on huponexit off interactive_comments on lithist off login_shell on mailwarn off no_empty_cmd_completion off nocaseglob off nocasematch off nullglob off progcomp on promptvars on restricted_shell off shift_verbose off sourcepath on xpg_echo off
If you disable the cmdhist setting by using the command shopt -u cmdhist, multi-line commands that previously would have been stored in a single line of your history file will be stored on multiple lines like so:
21 for num in 1 2 3 22 do 23 echo $num is nice 24 done
This might be useful if the complexity of your commands is all in the first line and maybe you want to issue a series of very different commands from different locations in your file systems within your do ... done. In any case, it's there should you find this option useful.
Those who cannot learn from history are bound to repeat it. Then again, so are those who do!