## 2.5. The hist Command

hist is a shell built-in command[31] that provides a superset of the C shell history mechanism. You can use it to examine the most recent commands you entered, to edit one or more commands with your favorite "real" editor, and to run old commands with changes without having to type the entire command in again. We'll look at each of these uses.

> [31] In ksh88, this command is called fc, for "fix command." ksh93 provides a built-in alias for fc to hist, for those who are used to using the fc command. Recent versions also have fc as a built-in command that behaves identically to hist; this is because POSIX requires that this command be built-in.

The -l option for hist lists previous commands. It takes arguments that refer to commands in the history file. Arguments can be numbers or alphanumeric strings; numbers refer to the commands in the history file, while strings refer to the most recent command beginning with the string. hist treats arguments in a rather complex way:

- If you give two arguments, they serve as the first and last commands to be shown.

- If you specify one number argument, only the command with that number is shown.

- With a single string argument, hist searches for the most recent command starting with that string and shows you everything from that command to the most recent command.

- If you specify no arguments, you will see the last 16 commands you entered. Thus, `hist -l` by itself is equivalent to the C shell history command, and indeed the Korn shell defines a built-in alias history as:

  >     alias history='hist -l'

  As you will find out in Chapter 3, this means that you can type `history` and the Korn shell will run the command `hist -l`.

A few examples should make these options clearer. Let's say you logged in and entered these commands:

>     ls -l
>     more myfile
>     vi myfile
>     wc -l myfile
>     pr myfile | lp -h

If you type `hist -l` (or `history`) with no arguments, you will see the above list with command numbers, as in:

>     1       ls -l
>     2       more myfile
>     3       vi myfile
>     4       wc -l myfile
>     5       pr myfile | lp -h

The option -n suppresses the line numbers. If you want to see only commands 2 through 4, type `hist -l 2 4`. If you want to see only the vi command, type `hist -l 3`. To see everything from the vi command up to the present, type `hist -l v`. Finally, if you want to see commands between more and wc, you can type `hist -l m w`, `hist -l m 4`, `hist -l 2 4`, etc.

Negative history numbers indicate values relative to the current command number. For example, `hist -l -3` shows the 3rd previous command. A less confusing way to to do this is with the -N option: `hist -l -N 3` does the same thing. This also has the advantage of conforming to the POSIX conventions for options and arguments.

The -l option to hist is not particularly useful, except as a quick way of remembering what commands you typed recently. Use the history alias if you are an experienced C shell user.

The other important option to hist is -e for "edit." This is useful as an "escape hatch" from vi- and emacs-modes if you aren't used to either of those editors. You can specify the pathname of your favorite editor and edit commands from your history file; then when you have made the changes, the shell actually executes the new lines.

Let's say your favorite editor is a little home-brew gem called zed. You could edit your commands by typing:

>     $ hist -e /usr/local/bin/zed

This seems like a lot of work just to fix a typo in your previous command; fortunately, there is a better way. You can set the environment variable `HISTEDIT` to the pathname of the editor you want hist to use. If you put a line in your .profile or environment file saying:

>     HISTEDIT=/usr/local/bin/zed

you get zed when you invoke hist. `HISTEDIT` defaults to the old line editor ed, so that the overall default is also ed.[32]

> [32] The default is actually a bit complicated in ksh93. `hist -e` runs `${HISTEDIT:-$FCEDIT}` to edit the command line. This preserves compatibility with ksh88, where the variable for the fc command was, not surprisingly, `FCEDIT`. If neither variable is set, you get /bin/ed. (The `${HISTEDIT:-$FCEDIT}` construct is explained in Chapter 4. The upshot is to use the editor specified by the `HISTEDIT` variable if it's set; otherwise use the value of the `FCEDIT` variable.)

hist is usually used to fix a recent command. Therefore, it handles arguments a bit differently than it does for the `hist -l` variation above:

- With no arguments, hist loads the editor with the most recent command.

- With a numeric argument, hist loads the editor with the command with that number.

- With a string argument, hist loads the most recent command starting with that string.

- With two arguments to hist, the arguments specify the beginning and end of a range of commands, as above.

Remember that hist actually runs the command(s) after you edit them. Therefore, the last-named choice can be dangerous. The Korn shell attempts to execute all commands in the range you specify when you exit your editor. If you have typed in any multiline constructs (like those we will cover in Chapter 5), the results could be even more dangerous. Although these might seem like valid ways of generating "instant shell programs," a far better strategy would be to direct the output of `hist -nl` with the same arguments to a file; then edit that file and execute the commands when you're satisfied with them:

>     $ hist -nl cp > lastcommands   List all commands that start with cp into lastcommands
>     $ vi lastcommands              Edit lastcommands
>     $ . lastcommands               Run the commands in it

In this case, the shell will not try to execute the file when you leave the editor!

There is one final use for hist. If you specify the option -s (i.e., type `hist -s`), the Korn shell will skip the editing part and just run the command(s) specified by the argument(s). Why is this useful? For one thing, just typing `hist -s` causes the previous command to repeat, just like the C shell `!!` command. The Korn shell provides the built-in alias r for this, so that if you type `r` and hit ENTER, you will repeat the last command.

This form of hist allows yet another type of argument, of the form `old``=`new, meaning "change occurrences of old in the specified previous command to new and then run it." (Unfortunately, you can't get the Korn shell to make this kind of substitution more than once; it only changes the first occurrence of old to new.) For example, suppose that you are using troff and its preprocessors to work on a document.[33] If you accidentally ran the tbl preprocessor with this command:

> [33] If so, you're one of a rare breed!

>     tbl ch2.tr | troff -ms -Tps > ch2.ps

but you needed to run eqn, you can redo it by typing `hist -s tbl=eqn`. (You could also use the alias, `r tbl=eqn`.) This command would then run:

>     eqn ch2.tr | troff -ms -Tps > ch2.ps

The Korn shell prints the modified command before running it.

Copyright © 2003 O'Reilly & Associates. All rights reserved.