Author: Mark Sobell
User Level: Intermediate
This article is excerpted from chapter 9 of the new Third Edition of A Practical Guide to Red Hat Linux: Fedora Core and Red Hat Enterprise Linux, copyright 2007 Pearson Education, Inc. ISBN 0132280272. Published June 2006 by Prentice Hall Professional. Reproduced by permission of Pearson Education, Inc. All rights reserved.
Variables that control history
The value of the HISTSIZE variable determines the number of events preserved in the history list during a session. A value in the range of 100 to 1,000 is normal.
When you exit from the shell, the most recently executed commands are saved in the file given by the HISTFILE variable (the default is ~/.bash_history). The next time you start the shell, this file initializes the history list. The value of the HISTFILESIZE variable determines the number of lines of history saved in HISTFILE (not necessarily the same as HISTSIZE). HISTSIZE holds the number of events remembered during a session, HISTFILESIZE holds the number remembered between sessions, and the file designated by HISTFILE holds the history list.
Variable |
Default |
Function |
HISTSIZE |
500 events |
Maximum number of events saved during a session |
HISTFILE |
~/.bash_history |
Location of the history file |
HISTFILESIZE |
500 events |
Maximum number of events saved between sessions |
The Bourne Again Shell assigns a sequential event number to each command line. You can display this event number as part of the bash prompt by including ! in the PS1 variable. Examples in this article show numbered prompts when they help to illustrate the behavior of a command.
Give the following command manually or place it in ~/.bash_profile (to affect future sessions) to establish a history list of the 100 most recent events:
$ HISTSIZE=100
The following command causes bash to save the 100 most recent events across login sessions:
$ HISTFILESIZE=100
After you set HISTFILESIZE, you can log out and log in again, and the 100 most recent events from the previous login session will appear in your history list.
Give the command history
to display the events in the history list. The list of events is ordered with oldest events at the top of the list. The following history list includes a command to modify the bash prompt so that it displays the history event number. The last event in the history list is the history
command that displayed the list.
32 $ history | tail 23 PS1="! bash$ " 24 ls -l 25 cat temp 26 rm temp 27 vim memo 28 lpr memo 29 vim memo 30 lpr memo 31 rm memo 32 history | tail
As you run commands and your history list becomes longer, it may run off the top of the screen when you use the history builtin. Pipe the output of history through less to browse through it, or give the command history 10
to look at the 10 most recent commands.
You can reexecute any event in the history list. Not having to reenter long command lines allows you to reexecute events more easily, quickly, and accurately than you could if you had to retype the entire command line. You can recall, modify, and reexecute previously executed events in three ways: You can use the fc builtin (covered next); the exclamation point commands; or the Readline Library, which uses a one-line vi- or emacs-like editor to edit and execute events.
If you are more familiar with vi or emacs and less familiar with the C or TC Shell, use fc or the Readline Library. If you are more familiar with the C or TC Shell and less familiar with vi and emacs, use the exclamation point commands. If it is a toss-up, try the Readline Library; it will benefit you in other areas of Linux more than learning the exclamation point commands will.
Next: Using fc
fc: Displays, Edits, and Reexecutes Commands
The fc (fix command) builtin enables you to display the history list and edit and reexecute previous commands. It provides many of the same capabilities as the command line editors.
When you call fc with the -l
option, it displays commands from the history list. Without any arguments, fc -l
lists the 16 most recent commands in a numbered list, with the oldest appearing first:
$ fc -l 1024 cd 1025 view calendar 1026 vim letter.adams01 1027 aspell -c letter.adams01 1028 vim letter.adams01 1029 lpr letter.adams01 1030 cd ../memos 1031 ls 1032 rm *0405 1033 fc -l 1034 cd 1035 whereis aspell 1036 man aspell 1037 cd /usr/share/doc/*aspell* 1038 pwd 1039 ls 1040 ls man-html
The fc builtin can take zero, one, or two arguments with the -l
option. The arguments specify the part of the history list to be displayed:
fc -l [ first[last[[
The fc builtin lists commands beginning with the most recent event that matches first. The argument can be an event number, the first few characters of the command line, or a negative number, which is taken to be the nth previous command. If you provide last, fc displays commands from the most recent event that matches first through the most recent event that matches last. The next command displays the history list from event 1030 through event 1035:
$ fc -l 1030 1035 1030 cd ../memos 1031 ls 1032 rm *0405 1033 fc -l 1034 cd 1035 whereis aspell
The following command lists the most recent event that begins with view through the most recent command line that begins with whereis:
$ fc -l view whereis 1025 view calendar 1026 vim letter.adams01 1027 aspell -c letter.adams01 1028 vim letter.adams01 1029 lpr letter.adams01 1030 cd ../memos 1031 ls 1032 rm *0405 1033 fc -l 1034 cd 1035 whereis aspell
To list a single command from the history list, use the same identifier for the first and second arguments. The following command lists event 1027:
$ fc -l 1027 1027 1027 aspell -c letter.adams01
You can use fc to edit and reexecute previous commands.
fc [-e editor] [first[last[[
When you call fc with the -e
option followed by the name of an editor, fc calls the editor with event(s) in the Work buffer. Without first and last, fc defaults to the most recent command. The next example invokes the vi(m) editor to edit the most recent command:
$ fc -e vi
The fc builtin uses the stand-alone vi(m) editor. If you set the FCEDIT
variable, you do not need to use the -e
option to specify an editor on the command line. Because the value of FCEDIT
has been changed to /usr/bin/emacs and fc has no arguments, the following command edits the most recent command with the emacs editor:
$ export FCEDIT=/usr/bin/emacs $ fc
If you call it with a single argument, fc invokes the editor on the specified command. The following example starts the editor with event 21 in the Work buffer. When you exit from the editor, the shell executes the command:
$ fc 21
Again you can identify commands with numbers or by specifying the first few characters of the command name. The following example calls the editor to work on events from the most recent event that begins with the letters vim
through event 206:
$ fc vim 206
When you execute an fc command, the shell executes whatever you leave in the editor buffer, possibly with unwanted results. If you decide you do not want to execute a command, delete everything from the buffer before you exit from the editor.
You can reexecute previous commands without going into an editor. If you call fc with the -s
option, it skips the editing phase and reexecutes the command. The following example reexecutes event 1029:
$ fc -s 1029 lpr letter.adams01
The next example reexecutes the previous command:
$ fc -s
When you reexecute a command you can tell fc to substitute one string for another. The next example substitutes the string john
for the string adams
in event 1029 and executes the modified event:
$ fc -s adams=john 1029 lpr letter.john01
Using an Exclamation Point (!) to Reference Events
The C Shell history mechanism uses an exclamation point to reference events, and is available under bash. It is frequently more cumbersome to use than fc but nevertheless has some useful features. For example, the !!
command reexecutes the previous event, and the !$
token represents the last word on the previous command line.
You can reference an event by using its absolute event number, its relative event number, or the text it contains. All references to events, called event designators, begin with an exclamation point (!
). One or more characters follow the exclamation point to specify an event.
You can put history events anywhere on a command line. To escape an exclamation point so that it is treated literally instead of as the start of a history event, precede it with a backslash () or enclose it within single quotation marks.
An event designator specifies a command in the history list.
Event designators
Designator |
Meaning |
! |
Starts a history event unless followed immediately by SPACE, NEWLINE, |
!! |
The previous command. |
!n |
Command number n in the history list. |
!-n |
The nth preceding command. |
!string |
The most recent command line that started with string. |
!?string[?] |
The most recent command that contained string. The last ? is optional. |
!# |
The current command (as you have it typed so far). |
!{event} |
The event is an event designator. The braces isolate event from the surrounding text. For example, !{-3}3 is the third most recently executed command followed by a 3. |
You can always reexecute the previous event by giving a !!
command. In the following example, event 45 reexecutes event 44:
44 $ ls -l text -rw-rw-r-- 1 alex group 45 Apr 30 14:53 text 45 $ !! ls -l text -rw-rw-r-- 1 alex group 45 Apr 30 14:53 text
The !!
command works whether or not your prompt displays an event number. As this example shows, when you use the history mechanism to reexecute an event, the shell displays the command it is reexecuting.
A number following an exclamation point refers to an event. If that event is in the history list, the shell executes it. Otherwise, the shell displays an error message. A negative number following an exclamation point references an event relative to the current event. For example, the command !-3
refers to the third preceding event. After you issue a command, the relative event number of a given event changes (event -3 becomes event -4). Both of the following commands reexecute event 44:
51 $ !44 ls -l text -rw-rw-r-- 1 alex group 45 Nov 30 14:53 text 52 $ !-8 ls -l text -rw-rw-r-- 1 alex group 45 Nov 30 14:53 text
When a string of text follows an exclamation point, the shell searches for and executes the most recent event that began with that string. If you enclose the string between question marks, the shell executes the most recent event that contained that string. The final question mark is optional if a RETURN would immediately follow it.
68 $ history 10 59 ls -l text* 60 tail text5 61 cat text1 text5 > letter 62 vim letter 63 cat letter 64 cat memo 65 lpr memo 66 pine jenny 67 ls -l 68 history 69 $ !l ls -l ... 70 $ !lpr lpr memo 71 $ !?letter? cat letter ...
Optional – Word Designators
A word designator specifies a word or series of words from an event.
Word designators
Designator |
Meaning |
n |
The nth word. Word 0 is normally the command name. |
^ |
The first word (after the command name). |
$ |
The last word. |
m–n |
All words from word number m through word number n;m defaults to 0 if you omit it (0-n). |
n* |
All words from word number n through the last word. |
* |
All words except the command name. The same as 1*. |
% |
The word matched by the most recent ?string? search. |
The words are numbered starting with 0 (the first word on the line — usually the command), continuing with 1 (the first word following the command), and going through n (the last word on the line).
To specify a particular word from a previous event, follow the event designator (such as !14) with a colon and the number of the word in the previous event. For example, !14:3 specifies the third word following the command from event 14. You can specify the first word following the command (word number 1) by using a caret (^) and the last word by using a dollar sign ($). You can specify a range of words by separating two word designators with a hyphen.
72 $ echo apple grape orange pear apple grape orange pear 73 $ echo !72:2 echo grape grape 74 $ echo !72:^ echo apple apple 75 $ !72:0 !72:$ echo pear pear 76 $ echo !72:2-4 echo grape orange pear grape orange pear 77 $ !72:0-$ echo apple grape orange pear apple grape orange pear
As the next example shows, !$ refers to the last word of the previous event. You can use this shorthand to edit, for example, a file you just displayed with cat:
$ cat report.718 ... $ vim !$ vim report.718 ...
If an event contains a single command, the word numbers correspond to the argument numbers. If an event contains more than one command, this correspondence does not hold true for commands after the first. In the following example, event 78 contains two commands separated by a semicolon so that the shell executes them sequentially; the semicolon is word number 5.
78 $ !72 ; echo helen jenny barbara echo apple grape orange pear ; echo helen jenny barbara apple grape orange pear helen jenny barbara 79 $ echo !78:7 echo helen helen 80 $ echo !78:4-7 echo pear ; echo helen pear helen
On occasion you may want to change an aspect of an event you are reexecuting. Perhaps you entered a complex command line with a typo or incorrect pathname, or you want to specify a different argument. You can modify an event or a word of an event by putting one or more modifiers after the word designator, or after the event designator if there is no word designator. Each modifier must be preceded by a colon (:).
The substitute modifier is more complex than the other modifiers. The following example shows the substitute modifier correcting a typo in the previous event:
$ car /home/jenny/memo.0507 /home/alex/letter.0507 bash: car: command not found $ !!:s/car/cat cat /home/jenny/memo.0507 /home/alex/letter.0507 ...
The substitute modifier has the following syntax:
[g]s/old_/new_/
where old is the original string (not a regular expression), and new is the string that replaces old. The substitute modifier substitutes the first occurrence of old with new. Placing a g before the s (as in gs/old/new/) causes a global substitution, replacing all occurrences of old. The / is the delimiter in the examples, but you can use any character that is not in either old or new. The final delimiter is optional if a RETURN would immediately follow it. As with the vim Substitute command, the history mechanism replaces an ampersand (&) in new with old. The shell replaces a null old string (s//new/) with the previous old string or string within a command that you searched for with ?string?.
An abbreviated form of the substitute modifier is quick substitution. Use it to reexecute the most recent event while changing some of the event text. The quick substitution character is the caret (^). For example, the command
$ ^old^new^
produces the same results as
$ !!:s/old/new/
Thus substituting cat for car in the previous event could have been entered as
$ ^car^cat cat /home/jenny/memo.0507 /home/alex/letter.0507 ...
You can omit the final caret if it would be followed immediately by a RETURN. As with other command line substitutions, the shell displays the command line as it appears after the substitution.
Modifiers (other than the substitute modifier) perform simple edits on the part of the event that has been selected by the event designator and the optional word designators. You can use multiple modifiers, each preceded by a colon (:).
The following series of commands uses ls
to list the name of a file, repeats the command without executing it (p modifier), and repeats the last command, removing the last part of the pathname (h modifier), again without executing it:
$ ls /etc/sysconfig/harddisks /etc/sysconfig/harddisks $ !!:p ls /etc/sysconfig/harddisks $ !!:h:p ls /etc/sysconfig $
This table lists event modifiers other than the substitute modifier.
Modifiers
Modifier |
Function |
e (extension) |
Removes all but the filename extension |
h (head) |
Removes the last part of a pathname |
p (print-not) |
Displays the command, but does not execute it |
q (quote) |
Quotes the substitution to prevent further substitutions on it |
r (root) |
Removes the filename extension |
t (tail) |
Removes all elements of a pathname except the last |
x |
Like q but quotes each word in the substitution individually |