In the early days of computing when even large systems had very little memory, if a user wanted to re-run a command, he or she had to re-enter the command at the prompt. As systems grew bigger and new shells were designed, the history mechanism was introduced.
The history mechanism will store and number each command line entered and allow you to recall it by number. It will also allow you edit it before running or even combine different parts of different previous command line entries to create a new command line sequence.
bash takes this even further and allows you to user the cursor keys to scroll through the list of stored command lines.
If you are logged on, press the [up] cursor key to see previously entered commands. Stop on a command of your choice and press [enter] to rerun or press [down] until the prompt with no commands reappears.
You may also see a list of all command lines currently stored in the history list by issuing the command history at the prompt. In our configuration of bash, this is a list of up to 1000 entries, so you may want to pipe it to less.
The bash history mechanism is configured using several shell variables.
HISTSIZE determines the number of command lines entered to remember for the current session. The more commands remembered the more likely you can recall an old command, but the more resources needed to keep the list. 1000 seems to be the current default.
If the history number of the current line is not already being displayed, you may set your prompt to display it.
PS1="\! >" HISTFILESIZE determines the number of lines to remember between shell sessions. When you log into the shell, unless it is your very first time, you will notice that the history list already has commands from a previous session. And if you are displaying the current command line count, it will not be 1. Each time you terminate a shell session, the current contents of the internal history list is written to a file. The number of lines remembered is set by this command. It is also currently set at 1000.
HISTFILE is the name of the file in which the history list is copied when a shell session terminates. It is normally set to .bash_history in your home directory, but you may change this by setting HISTFILE in the shell configuration file. If HISTFILE is unset, commands from the previous session will not be remembered.
There are several other variables available to fine tune the behavior of the history mechanism. Once you are comfortable with history's basic behavior, see the "HISTORY" section in the bash man page.
Although scrolling up to a previous command and pressing [enter] is the easiest way to re-run a command, sooner or later, you will need to modify the retrieved command in some way before running it.
The history mechanism and the bash shell allow several ways to do this. The simplest is fetch the line, use [left] and [right] cursors to move across the line and use [del] to delete what you don't want and type in what you want. Then press [enter] to run. If you need fancier editing capabilities, you may use Emacs or vi style editing commands on the line. The default is Emacs but you can switch to vi style editing by running set -o vi at the prompt.
Rather than scrolling to a previous command, you may recall it immediately by using the ! or bang and referencing command's history line number. To fetch back line 233, use :
!233
The exclamation or bang is the history reference symbol and indicates that we wish to recall line 233 from the history list. Remember that while our list is long, it is not unlimited. If the current history line is 2023 and you list is 1000 lines long, line 233 is no longer available.
History provides a shortcuts to help recall a command.
To rerun the last command entered, use just a double bang.
!!
To recall the most recently entered ls command, use the bang and the ls
!ls
If you wish to recall a previous command line but you don't wish to execute it, use the :p modifier, for print. This will cause the line to be re-entered into the history queue without being run.
!233:p
In the old days, when the history list was 100 lines rather than 1000, this was the way to renew the entry in the history until you were ready to run it.
Suppose you enter the command sequence :
find $HOME|sort -r > sorted
History would number it as follows :
find | $HOME | | | sort | -r | > | sorted |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
Note that even though there were no spaces on either side of the pipe, it is given its own index reference.
On the other hand, it treats an unbroken string of characters that it doesn't recognize as delimiters as a single argument
data="hi there"
The history mechanism would count this a single unit and k History would number it as follows :
find | $HOME | | | sort | -r | > | sorted |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
Because each element on the line is numbered, we can recall different elements different lines. Lets say we run the following commands, the first does a long listing on a filename we suspect is a directory and the second does a short listing just to confirm its existence. Once we know both satisfy our criteria, we will copy the second file into the first, a directory. The line count is now part of the prompt.
204 > ls -ld $HOME/DATA/assn2 drwxr-xr-x 89 berezin user 4096 2007-06-27 22:08 /home/hopper/berezin/DATA/assn2 205 > ls assn2.data assn2.data 206 > cp !205:1 !204:2 207 >
You may call any element from any line still in the history list. You may specify them in any order and more than once if desired.
h - head - list everything up to the last / in the filename.
t - tail - list everything after the last / in the filename.
r - root - list everything up to the last extension in the filename
e - extension - list just the last extension.
208 > echo /home/hopper/berezin/assn1.data.ver1 /home/hopper/berezin/assn1.data.ver1 209 > echo !208:1:h /home/hopper/berezin 210 > echo !208:1:t assn1.data.ver1 211 > echo !208:1:r /home/hopper/berezin/assn1.data 212 > echo !208:1:e ver1
It is possible to combine these although some may not make sense.
213 > echo !208:1:t:r assn1.data 214 > echo !208:1:r:r /home/hopper/berezin/assn1
Another feature of the history mechanism is the ability to substitute elements on the command line.
215 > echo !208:1:s/berezin/z912730 /home/hopper/z912730/assn1.data.ver1
If you wish to substitute on the last command line entered, use the ^ shortcut.
216 > ^z912730^t90jxb1 /home/hopper/t90jxb1/assn1.data.ver1
If you need to do multiple substitutions, combine the substitution with the print to suppress the execution until all changes made.
217 > echo !208:1:p:s/berezin/z912730:p echo /home/hopper/z912730/assn1.data.ver1 218 > echo !217:1:s/hopper/mp /home/mp/z912730/assn1.data.ver1
If you wish to substitute a string with spaces with a non-spaced string, the substitution is straight forward. However, the replacement string has spaces, you will need to use the backslash.
219 > echo pear apple pear apple 219 > !219:s/pear apple/peach\ plum peach plum