Interactive Korn Shell for Bash Users
by F. William Lynch

With thanks to Dave Herrald and Andrew Green

Which OSes use ksh?

Sometimes you might need to use an OS without bash. Fortunately, most of the features which make the bash shell an excellent interactive shell are also present in the Korn shell (my personal favorite shell). In fact, many of the Korn shell features were copied and improved upon by the developers of bash.

The following OSes either include or use ksh by default:

Solaris (and AIX?) include ksh88

xBSD and some distros of Linux include pdksh
SCO OpenServer and Unixware include ksh (88?)

Later versions of Slackware include ksh93
If you know of others, e-mail me so I can add them to the list.

The following code snippet can be used in ksh to give a bash like prompt:

export HOSTNAME=`/bin/hostname`                                                 
PS1='[$USER\@$HOSTNAME ${PWD##/*/}]$ '                                          

I discovered this more or less through trial and error, though the $ won’t change to # when running as root.

Command History (vi mode)

The fc command: a brief history lesson

Take a look at the fc (fix command) man page. This command works almost exactly like the fc command in bash. You feed it the number of your

previous history command and its execution is repeated. This command was actually introduced as history in the C shell, but has evolved

since. By default, fc allows you to edit your previous commands with the ed editor (which can be changed by modifying the FCEDIT shell variable.

Clearly, the Korn shell’s command line editing features are more advanced and easier to use, however, there are three such cases where fc can be handy:

Case 1: Repeating the Last Command Explicitly

You may already be familiar with the fc operator “r” (bash/csh equivalent is “!!”) which is a built-in alias that repeats the last command issued.

Of course, if you prefer to use the !! syntax, you can use the following alias:

alias \!\!='fc -e -'                                                            

Case 2: Repeating the Last Command with Replacement

If you’re repeating the last command with only a slight modification, fc works great also. For example, suppose you ran this command:

                                                                           mv app-09.26.00.log oldlogs                                                     

And you also want to move the file app-09.25.00.log to the oldlogs directory. In this case, you could use fc to accomplish your goal in less keystrokes.

fc -e - 26=25                                                                   

or, you could use the Korn shell shortcut like this:

                                                                           r 26=25                                                                         

or even using the alias specified above:

!! 26=25                                                                        

Case 3: [ESC]-v and Full vi Editing

Alternatively, you can edit the entire command line with vi using the “v” command. This type of editing can be especially helpful for editing “for”

or “while” loops that span multiple lines. This is actually another fc alias that edits the current line in full screen vi mode. However, since the
command is executed immediately upon exiting vi, you should pay extra attention to the command syntax, especially when editing commands as root.

Command Line Editing in vi Mode

Instead of using fc to edit your previous commands, it’s usually easier to use ksh built-ins in vi mode.

You can use vi mode by setting the option like this:

set -o vi (when in ksh already) OR ksh -o vi (when launching a ksh shell)

In this mode, you’ll want to get familiar with a few commands:

Previous Command —-> [ESC]-k Use this key combination to access your previous command
Next Command —-> [ESC]-j Use this key combination to access your next command (if applicable)
Filename Completion —-> [ESC]-\ Use this key combination to complete a filename, or partial portion thereof
Filename Check —-> [ESC]-= Use this key combination to show which files would complete the command at this point


  • There is no command completion in ksh88, though there is in ksh93.
  • There is no tab completion in ksh88, though there is in pdksh and ksh93
  • To use tab-complete in pdksh, you may need to use set -o vi-tabcomplete
  • To use tab-complete in ksh93 you may need to use set -o viraw

Commands can be editing using the standard vi editing keys, however, the arrow keys are not standard vi editing keys.

  • There is no way (that I have discovered) to use arrow keys in ksh88
  • Arrow keys should work fine in pdksh
  • Arrow keys in ksh93 may need special key-bindings to work. Some samples are available here from

Finally, you can also find the last command you typed that included a certain string. This can often be faster than searching through

previous command lines one at a time. To do so, use the syntax


where string is the text string you’re searching for. You can also use the “N” and “n” to move forward and backward in your searches, respectively.

Other ksh Interactive Features (vi mode)
Command-line Editing

In conjunction with recalling your previous commands, you can also edit these commands.

A subset of the most common editing commands are listed below.

Forward One Character —-> —-> [ESC]-l
Backward One Character —-> [ESC]-h
Delete One Character —-> [ESC]-x
Replace One Character —-> [ESC]-r
Forward End of Word —-> [ESC]-e
Backward Beginning of Word —-> [ESC]-b
Delete to End of Line —-> [ESC]-D
Insert Text (current space) —-> [ESC]-i
Insert Text (adjacent space) —-> [ESC]-a
Move Cursor to Beginning of Line —-> [ESC]-^
Move Cursor to End of Line —-> [ESC]-$

Note: The [ESC] key is not necessary if you are currently in command-mode.

Job Control
Job control under the Korn shell actually works identically to job control under the bash shell. However, since its a very useful
interactive shell feature, I’ll summarize its uses here.

Suppose for example you want to watch the system messages on a Solaris box, you might run this command:

# tail -f /var/adm/messages                                                     

But perhaps something isn’t logging correctly and you need to make some changes to /etc/syslog.conf. You decide to send ^Z (suspend)

to your tail process like this:

                                                                           ^Z[1] + Stopped (SIGTSTP)        tail -f /var/adm/messages                      

You still want the process to run however, so using the number in brackets, you send the process to the background like this:

                                                                           # bg %1                                                                         
[1]     tail -f /var/adm/messages&                                              

Now, you’re free to make your syslog changes, and when you’re ready to return to your tail process you’ve forgotten which job it was.

In this case, you would use the jobs command to see which jobs are tasked to the current shell like this:

                                                                           # jobs                                                                          [3] + Stopped (SIGTSTP)        ls -al /dev | more                               [2] - Stopped (SIGTSTP)        find / 2>&1 > /dev/null                          
[1]   Stopped (SIGTSTP)        tail -f /var/adm/messages                        

Once you know what the job number is, you can return the job to the foreground using the command:

# fg %1                                                                         tail -f /var/adm/messages                                                       

Note that if the job number is not specified the most current active job, indicated by the “+” is

the default job. So, fg with no arguments would bring job 3 to the foreground.

Alternatively, if you wanted to kill the job at this point, this could be accomplished by using
the kill command in the following manner:

                                                                           # kill %1                                                                       [1] + Terminated               tail -f /var/adm/messages                        

Thus, we can easily see how useful job control can be, especially if you have a limited number of login shells available.

The following references were used in making this guide:
Learning the Bash Shell from O’Reilly
Learning the Korn Shell from O’Reilly

About the Author

F. William Lynch is a technology consultant in Denver, CO. He spends every waking hour either in
front of a computer, practicing martial arts or watching hockey.