Unix Command Line Editing

Using history and command line editing

One of the great features of the C shell and the Korn shell is history. The ability to recall and reuse commands that you have entered earlier can save many keystrokes of repetitive typing. History and command line editing are closely related. You may use command line editing to edit the command that you are currently working on after you have typed it in, or you may recall a previous command and then edit it.

In this article, I will show you some of the ins and outs of history and command line editing in the Korn shell. For history to work, you need to be in the Korn shell, so begin by typing:

ksh

to launch a Korn shell.

The second thing you need to make history work is an easy way to access it. History is more than just the ability to recall previous commands; it lets you recall commands and edit them before they are executed. The Korn shell allows you to use different editing styles depending on what you're trying to do. The primary editors are vi, emacs, and gmacs. I recommend vi, as most people are familiar with it. History and command line editing behave very differently depending on whether you are using vi, emacs, or gmacs. I will cover some of these differences.

To set vi up as your history editor type:

set -o vi

If you are going to continue to use history, you will want to include this in your profile, or the emacs/gmacs equivalents. These set -o commands only work in the Korn shell:

set -o emacs
or
set -o gmacs

Assuming that you have set -o vi as your history editor, you may now access history. Press the escape key once (esc) and release it and press k. The last command that you typed will appear on the screen:

$ set -o vi

Press enter and that command will be executed. Try a few more commands so that you can accumulate some history. End with ls -l on the current directory. Now press esc and k. The ls -l command appears once more. Press k again and the command just prior to ls -l will appear. Each time you press k you'll go back one more command in your history. The minus key ( - ) works in exactly the same way. I use the minus key because it's easier for me to remember. Eventually, if you press k or minus enough times, you'll end up back at the set -o vi command.

Now press j or the plus key < + > and you will move forward in the command history. (When you are rapidly running back through history looking for the command you need, and you realize you've passed it, it's good to know how to move forward again.)

If you have set -o emacs or gmacs, the keys are control-p for previous command and control-n for next command. In vi you hit esc once and then k or n will move you backward or forward through the commands. For emacs and gmacs, use control-p or control-n each time.

To view more of your history, type "history", and a list of your most recent commands will be displayed along with numbers. If you see the number of a command that you need, recall it by hitting the esc key, typing the number of the command as displayed by history, and then typing an upper case G. This will place the command with that number on the command line.

Once you have located the command that you want, you can press enter to execute the command, but you can also edit the command before executing it.
 

Moving around in vi
There are several vi commands for moving around the command line and editing the line. I will only cover a few here. For further information consult the manual on ksh. If you are familiar with vi you will recognize the commands. The vi editor operates in two main modes. In command mode single keys move the cursor, delete characters and perform other actions. In input mode single keys are actually typed into the command line.

Command Editing -- Cursor Movement in command mode for vi

l (el)    Move the cursor forward one character
h         Move the cursor back one character
w         Move the cursor forward one word
b         Move the cursor back one word
fc        Find character c in the line
0 (zero)  Cursor to the start of the line
$         Cursor to the end of the line

l, h, w, f and b can be preceded by a number, thus 2b moves the cursor back two words, and 3fx finds the third occurrence of x in the line. In emacs and gmacs mode, cursor movement is different.

Command Editing -- Cursor Movement in emacs/gmacs

CONTROL-F        Move the cursor forward one character
CONTROL-B        Move the cursor back one character
ESCAPE then f    Move the cursor forward one word
ESCAPE then b    Move the cursor back one word
CONTROL-A        Cursor to the start of the line
CONTROL-E        Cursor to the end of the line

The editing of a command line is not limited to history. You can also edit a command line that you are currently typing in. For example type the following, but do not press enter:

ls -l

You should be sitting with the cursor at the end of the command line. If you have set -o vi then hit the esc key to exit input mode and enter command mode. Now you can type h a few times and the cursor will move backward through the command line. If you have set -o emacs, there is no need to press esc, just start by typing control-b a few times, and the cursor will move backwards.

Now we have the cursor where we want it, but how do you actually edit the command? There are several editing options, and again I am going to describe just some of the more useful ones.

Command Editing -- Editing keys in command mode for vi

x         Delete the character over the cursor. Can be preceded by a count
X         Delete the character behind the cursor. Can be preceded by a count
~ (tilde) Change case of the character over the cursor. Can be preceded by a
count
u         Undo the last change to the line
U         Undo all changes to the line
a         Enter input mode and begin inserting after the current character
A         Enter input mode and begin inserting at the end of the line
i         Enter input mode and begin inserting before the current character
I         Enter input mode and begin inserting at the beginning of the line

You enter input mode by pressing a, A, i or I. To exit to command mode, press the esc key.

You may also press enter at any time, and the command as it appears on the command line will be executed.

In emacs and gmacs mode, you are always in input mode and normal characters that are typed appear in the command line. Editing commands are given as control + key or as esc + key ("key" is a variable).

Command Editing -- Editing keys for emacs/gmacs

CONTROL-D         Delete the character over the cursor
ESCAPE then d     Delete the current word
CONTROL-C~        Capitalize current character
ESCAPE then l     Convert current character to lower case

In emacs and gmacs mode, you may also press enter at any time, and the command, as it appears on the command line, will be executed.

Remember that command line editing applies to the current command that you are typing, or any other command that you have recovered from your history.
 

Fun with file name completion
The last piece of command line editing that I want to cover is file name completion. This is usually used in current command lines but of course it can also be used when editing a command retrieved from history.

Assume a directory and file structure as follows and you are currently in the abc directory.
 

(dir)                  topdir
            |
            -------------------------------
            |            |                |
(dir)      abc          def              ghi
(files)  data.txt     john.ltr         news.doc
         old.txt      john.txt       weather.doc

Type the following but do not press enter:

ls -l d

Now hit esc and then the backslash ( \ ). This causes the command line editor to attempt to locate a file (or directory) that can be used to complete the name that has been started. The search finds data.txt and that is typed in on the command line:

ls -l data.txt

The cursor is left after the txt of data.txt ready for you to type anything else that is needed to complete your command line.

This also works for directories. Assume, for example, that you are in the abc directory and need to edit news.doc in the ghi directory. You have the option to go to that directory and begin editing, or simply issue a vi command to edit directly from where you are:

cd ../ghi
vi news.doc

or

vi ../ghi/news.doc

If you try the following sequence you will see the ( \ ) at work completing the names for you. First type enough of the command to identify the directory:

vi ../g

Now type esc followed by ( \ ) and the directory name is completed for you:

vi ../ghi/

Now type enough to uniquely identify the file by adding an n:

vi ../ghi/n

Press esc followed by ( \ ) and the file name is completed for you:

vi ../ghi/news.doc

This feature is especially useful for long directory and file names and will save you much typing.

If two or more files match what you have typed so far, the file completion option will complete as much of the file as it can and then wait for you to provide more unique input. To edit the file john.txt from one of the adjacent directories type:

vi ../def/j

Press esc and backslash and it will fill in as much as it can and then wait for you to indicate whether you want john.txt or john.ltr:

vi ../def/john.

The sequence that does this for emacs and gmacs is esc followed by a second esc.

There is much more to command line editing and history, but I have found that just these few tips greatly speed up my work, and I hope they do the same for you.

If you like the idea of history, ask your system administrator to change your shell to a Korn shell, and then be sure to add set -o vi, emacs or gmacs into your .profile file.

======================================
http://www.yahoo.com/Computers_and_Internet/Software/Text_Editors/vi/ - yahoo
http://teche.cacs.usl.edu/tutorial/unix-vi/tableofcontents3_2.html - The Association for Computing Machinery's vi manual pages
http://www.wcmh.com/uworld/archives/95/tutorial/009/009.html - A vi tutorial in UnixWorld Online
http://www.cs.vu.nl/~tmgil/vi.html - The vi lovers home page with information on vi and it's descendants vim, elvis, vile and others as well as links to other vi pages
http://cres20.anu.edu.au/manuals/korn_scr.html - Korn shell course notes
http://www.cs.stir.ac.uk/guides/unix/unix.html - Notes on using and programming the Korn shell
http://www.sun.com/sunworldonline/common/swol-backissues-columns.html#unix101  - Full listing of previous Unix 101 columns in SunWorld

======================================
Main Editing Commands for emacs mode:
If you are using tcsh (T-C-shell), then command line editing is built-in and you can simply use it.

If you are using Korn shell (ksh), your login file (.profile) must contain the line
    set -o emacs
before command line editing will work. You can also type this at the command prompt.  This step is not necessary if your default shell is tcsh

Specific Editing Commands:
Previous command:    ^P
Next command:    ^N
Back 1 character:    ^B
Forward 1 character:    ^F
Delete 1 character:    ^D  (NOTE: if you are not editing a command, ^D will log you out.)
Execute the retyped command:     <ENTER> key

Depending on the telnet program (terminal emulator) you are using, the cursor control keys on your keyboard may work. Try it and see.  If so, then you only need remember how to delete a character.

'Broken' Delete Key

If the DELETE key produces unexpected results, there is a way to correct this.  If you type ^C (control-C) to abort the current command line, and then carefully type:

    stty erase [^H]

where [^H] represents your pressing the key that you want to be a backspace/delete key, and then press the ENTER key, then you will have reset the backspace/delete key for your current session. You can also use and editor (pico, emacs, or vi) to put this in your .login or .profile file and it will be set every time you login.

File name completion:

Hitting the escape key twice after you have typed enough characters of a file name to make it unique will enable the file-name completion feature of ksh, and the shell will fill in the remainder of the file name for you.

======================================