Introduction to KornShell


Most UNIX variants allow you to select among several shells . Because of its versatility and ease of use, many system administrators configure the KornShell for new users. The KornShell was derived from the Bourne Shell and has much of the same functionality of the Bourne Shell. ksh is the program you run on most UNIX systems, including HP-UX, that supplies KornShell functionality. It is also often referred to as the K shell. I use ksh throughout this chapter. You can use the ksh in the following three ways:

  • Interactively type commands on the command line.

  • Group commonly executed sets of commands into command files that you can execute by typing the name of the file.

  • Create KornShell programs using the structured programming techniques of the shell.

These three techniques are listed in the order in which you'll probably use them. First, you log in and use interactive commands. Then you group together commonly used commands and execute them with a single command. Finally, you may want to create sophisticated shell scripts.

For this reason, I describe these aspects of the KornShell in the order in which they are listed. The command file and programming aspects of the KornShell are covered as part of the Shell Programming Chapter 28.

The examples in this chapter are performed on a variety of different systems, not just HP-UX. This is because many system administrators use ksh on several different UNIX variants. You would probably find both your user setup and the operation of the KornShell on other systems similar to the description in this chapter. Much of the setup of any shell is performed by the system administrator, so you will surely find differences in your KornShell setup compared with what is shown in this chapter. In general, however, the operation of the KornShell is similar from one system to another.

Startup Files

The first activity you perform after you log into the system is to issue commands at the prompt. A command you may want to issue immediately is ls -al . Here is what I see on my system after executing this command, producing a long listing of all files:

 martyp $  ls -al  total 22 drwxr-xr-x   2 martyp   staff        512 Mar 15 11:37. drwxrwxr-x   4 root     sys          512 Mar  4 09:24 .. -rw-r--r--   1 martyp   staff        124 Mar 15 11:36 .cshrc -rw-r--r--   1 martyp   staff        562 Mar  4 09:24 .profile -rw-------  1 martyp   staff      7056 Apr  6 07:24 .sh_history martyp $ 

This produces a short list of files. Some of these files, such as .profile and .cshrc , are startup files for ksh and the C shell, respectively. Upon logging in to a system, you normally execute system startup files for your shell and then execute any local startup files that you have in your home directory. In this case, I have a minimal ksh startup file in my home directory - only a .profile that has very little in it. Virtually all the startup activity for this user comes from the system profile, usually /etc/profile. You can usually read /etc/profile , so you can see what your system administrator has set up for you and other users. You can then modify your local .profile to include a variety of functionality. Your local .profile is usually run at login, immediately after the system /etc/profile .

After running all the startup scripts associated with your ksh login, your environment is set up for you. Although our local .profile didn't do much other than set up our prompt, a lot of setup took place with the system files that were run.

Another file you have is called the Environment file. This file name is defined by the environment variable ENV . This file is usually . kshrc in your home directory. Using the environment file, you can define which options, aliases, and other information will be passed to subprocesses. By default, your existing environment variables are passed to subprocesses. You can use the environment file to pass other information along as well.

You should take a look at your ksh startup files, including /etc/profile, .profile , and .kshrc .

We'll discuss much of the specific ksh functionality provided for you as part of your startup programs in the upcoming sections.

The History File, .sh_history

ksh keeps a history list of the commands you have issued. If you wish to reissue a command or view a command you earlier issued, you can use the history list. By default, .sh_history in your home directory is used as a history file. When your system administrator creates your ksh home directory, this file is probably present and used as your default history file.

By default, most systems save the 128 most recently executed commands. You can specify any number of commands to be included in the history list. The following line sets the history list to 200:

HISTSIZE=200

Most users make this entry in their home .profile . After you have added this line to your .profile , the history list is set to 200 .

Recalling from the History List

You can view the most recent commands issued, along with their corresponding line numbers , with the history command as shown in the following example:

 martyp $  history  116     history 128 117     history 128  more 118     history 200 119     alias 120     history 1 121     inv 122     env 123     env  more 124     history 1 125     more .profile 126     env  grep HIS 127     exit 128     env 129     env  grep HIS 130     more .profile 131     history martyp $ 

Notice in this example that command number 127 is the exit , or command to log out, from the last session. Command number 128 is the env command I issued immediately upon establishing the next session.

We can also print the history list without line numbers using the -n option, as shown in the following example:

 martyp $  history -n  history 128  more         history 200         alias         history 1         inv         env         env  more         history 1         more .profile         env  grep HIS         exit         env         env  grep HIS         more .profile         history         history -n martyp $ 

To produce a complete list of commands in the history list, we issue the following command:

 martyp $  history 0  5       env 6       more .profile 7       set 8       env  grep CDP 9       env  grep cdp 10      echo $SHELLL 11      echo $SHELL 12      more .profile 13      ll 14      ls -al /etc/profile 15      more /etc/profile 16      more /etc/profile  grep PS 17      exhoecE 18      ECHO 19      echo $ENV 20      env  more 21      echo $ENV 22      env  more 23      env  grep ENV 24      env  grep env 25      more /usr/bin/env 26      ls -al 27      more /etc/.kshrc 28      find / -name .kshrc 29      more /etc/passwd 30      more /etc/passwd  grep /home 31      ll /home/oracle 32      ls -al /home/oracle 33      ll /home 34      ls -al /home 35      ls -al /home/ptc-nfs 36      ls -al /home/ptc-nfs  more 37      ls -al /root 38      cd /root/users 39      ls -al 40      ls -al verasu 41      ls -al rodtsu 42       cd rodtsu 43      more .kshrc 44      more .env 45      ls 46      ls -l 47      ls -a 48      more .kshrc 49      cd .. 50      ls -al 51      ls -al  more 52      exit 53      ls -al 54      more .sh* 55      history 56      env  grep his 57      env  grep HIS 58      env  grep IS 59      env  more 60       env  grep FC 61      env  grep EDI 62      history 63      echo $HISTIZE 64      echo $HISTSIZE 65      env  more 66      ls -al 67      history 128 68      history 69      history 1 104 70      exit 71      alias 72      more /etc/profile  grep alias 73      ll 74      la -al 75      ls -al 76      more .profile 77      ls -al 78      more .cshrc 79      alias ll="ls -al" 80      aliase 81      alias 82      ll 83      exit 84      alias 85      alias 86      history 87      fc -l 88      man fc 89      man fc 90      man fc 91      alias 92      ps 93      ps -ef 94      ps -efl 95      ps 96      ls -alF 97      ls -al 98      alias ls="ls -al" 99      alias 100     ls 101     alias 102     unalias ls 103     ls 104     ls -al 105     alias 106     history 107     alias 108     unalias history 109     history 110     fc -l 111     history 112     alias hisotry="fc -l" 113     history 114     alias history="fc -l" 115     history 116     history 128 117     history 128  more 118     history 200 119     alias 120     history 1 121     inv 122     env 123     env  more 124     history 1 125     more .profile 126     env  grep HIS 127     exit 128     env 129     env  grep HIS 130     more .profile 131     history 132     history 0 martyp $ 

history 0 prints from the very first command, zero, to the present command. Because only 128 commands are saved by default, the first few oldest commands, zero through four, dropped off the history list. This means that we really started at command number five when we requested to start the list from command number zero.

To produce a list from command 100 to the present command, we issue the following:

 martyp $  history 100  100     ls 101     alias 102     unalias ls 103     ls 104     ls -al 105     alias 106     history 107     alias 108     unalias history 109     history 110     fc -l 111     history 112     alias hisotry="fc -l" 113     history 114     alias history="fc -l" 115     history 116     history 128 117     history 128  more 118     history 200 119     alias 120     history 1 121     inv 122     env 123     env  more 124     history 1 125     more .profile 126     env  grep HIS 127     exit 128     env 129     env  grep HIS 130     more .profile 131     history 132     history 0 133     history 134     history -n 135     history 100 martyp $ 

To list the current command and the 20 commands preceding it, we issue the following:

 martyp $  history -20  116     history 128 117     history 128  more 118     history 200 119     alias 120     history 1 121     inv 122     env 123     env  more 124     history 1 125     more .profile 126     env  grep HIS 127     exit 128     env 129     env  grep HIS 130     more .profile 131     history 132     history 0 133     history 134     history -n 135     history 100 136     history -20 martyp $ 

The -20 goes back from the current command a full 20 commands. In this case, history is using the current command as the default place to begin producing the list. You can list the last 20 commands preceding the current command by specifying the range -1 -20 as shown in the following example:

 martyp $  history -1 -20  136     history -20 135     history 100 134     history -n 133     history 132     history 0 131     history 130     more .profile 129     env  grep HIS 128     env 127     exit 126     env  grep HIS 125     more .profile 124     history 1 123     env  more 122     env 121     inv 120     history 1 119     alias 118     history 200 117     history 128  more martyp $ 

Notice in this example that the current command, history -1 -20 , is not shown in the list because the -1 starts the list with the preceding command. This is effectively producing a range of commands to list.

You can also reverse the order of the last 20 commands by specifying --20 first and then the -1 as shown in the following example:

 martyp $  history -20 -1  118     history 200 119     alias 120     history 1 121     inv 122     env 123     env  more 124     history 1 125     more .profile 126     env  grep HIS 127     exit 128     env 129     env  grep HIS 130     more .profile 131     history 132     history 0 133     history 134     history -n 135     history 100 136     history -20 137     history -1 -20 martyp $ 

You can also produce a list from the last time that a command was issued to the current command. The following example shows producing a list from the last fc command to the current command:

 martyp $  history fc  110     fc -l 111     history 112     alias hisotry="fc -l" 113     history 114     alias history="fc -l" 115     history 116     history 128 117     history 128  more 118     history 200 119     alias 120     history 1 121     inv 122     env 123     env  more 124     history 1 125     more .profile 126     env  grep HIS 127     exit 128     env 129     env  grep HIS 130     more .profile 131     history 132     history 0 133     history 134     history -n 135     history 100 136     history -20 137     history -1 -20 138     history -20 -1 139     history 140     history grep 141     history env 142     history 143     history fc martyp $ 

You can also reverse this list using the -r option as shown in the following example:

 martyp $  history -r fc  144     history -r fc 143     history fc 142     history 141     history env 140     history grep 139     history 138     history -20 -1 137     history -1 -20 136     history -20 135     history 100 134     history -n 133     history 132     history 0 131     history 130     more .profile 129     env  grep HIS 128     env 127     exit 126     env  grep HIS 125     more .profile 124     history 1 123     env  more 122     env 121     inv 120     history 1 119     alias 118     history 200 117     history 128  more 116     history 128 115     history 114     alias history="fc -l" 113     history 112     alias hisotry="fc -l" 111     history 110     fc -l martyp $ 

Having access to this history list is a great feature of the KornShell. You can view all the commands you have issued, including your typing errors, in any format you wish. In the next section, we start using the commands in the history list by recalling them.

Re-executing Commands with r

You can reissue a command with the r command. To reissue the last command, you simply type r . In the following example, I issue the command history 5 to view the last five commands from the history list. I then type r to reissue the last command, and again the last five commands are listed:

 martyp $  history -5  301     whoami 302     pwd 303     more /etc/passwd 304      ps -efl 305     cat .profile 306     history -5 martyp $ r history -5 302     pwd 303     more /etc/passwd 304      ps -efl 305     cat .profile 306     history -5 307     history -5 martyp $ 

You can reissue a specific command number by typing r , a space, and the number of the command you wish to reissue. In the following example, I issue the history command number 302:

 martyp $  history  294     history -5 295     whoami 296     pwd 297     more /etc/passwd 298     ps -efl 299     cat /etc/profile 300     history 5 301     whoami 302     pwd 303     more /etc/passwd 304      ps -efl 305     cat .profile 306     history -5 307     history -5 308     history -5 309     history martyp $  r 302  pwd /home/martyp martyp $ 

You can also give the name of the command you wish to reissue. Let's say that you want to reissue the last fc command. You would simply give the letter "f" along with the r command, and the last command that started with f would be reissued as shown in the following example:

 martyp $  history  308     history -5 309     history 310     pwd 311     whoami 312     pwd 313     cat /etc/profile 314     ls 315     fc -l 316     env 317     who 318     cat /etc/passwd 319     ls -al 320     history 321     more .profile 322     set 323     history martyp $  r f  fc -l 309     history 310     pwd 311     whoami 312     pwd 313     cat /etc/profile 314     ls 315     fc -l 316     env 317     who 318     cat /etc/passwd 319     ls -al 320     history 321     more .profile 322     set 323     history 324     fc -l martyp $ 

You can also perform some substitution with the r command. If you issued the vi command earlier and want to rerun vi but specify a different file name to edit, you can substitute a new file name. The following example shows reissuing an earlier vi command, except now we'll replace the original filename we edited, .profile , with the new filename we want to edit, .kshrc . In this example, we'll first run the history command, then reissue the vi command to edit .kshrc , and then we'll run the command again to see our revised vi command:

 martyp $  history  316     env 317     who 318     cat /etc/passwd 319     ls -al 320     history 321     more .profile 322     set 323     history 324     fc -l 325     vi .profile 326     set 327     ls -al 328     env 329     who 330     more /etc/passwd  grep marty 331     history martyp $  r vi .profile=.kshrc  martyp $  history  318     cat /etc/passwd 319     ls -al 320     history 321     more .profile 322     set 323     history 324     fc -l 325     vi .profile 326     set 327     ls -al 328     env 329     who 330     more /etc/passwd  grep marty 331     history 332     vi .kshrc 333     history martyp $ 

This command substitutes .kshrc for .profile on the command line.

This leads us to more advanced command-line editing. You may want to recall a command earlier issued and edit the command line using vi editor commands. The next section covers command-line editing.

Fetching Commands Using vi Directives

You can edit entries in your history list with either the vi or emacs editor. I will cover the vi editor in this chapter, because it is the most widely used on UNIX systems. You can, however, perform all the same functions shown in this chapter with the emacs editor.

You edit the history list using vi the same way you edit a file using vi . You press the escape key and use standard vi keys for moving up and down, left and right, inserting deleting, and changing text. In this section, I cover fetching a command from the history list using vi commands and then I cover editing the command after you have restored it to the command line. After the command has been edited to your liking, you press enter to execute the command and place it at the very bottom of the command list.

Your editor is normally set in either your local .profile or /etc/profile . You can view these files to see what editor has been set for you by your system administrator. When I issue the env and set commands on my system, both report EDITOR=vi . This corresponds with my /etc/profile which has the editor set to vi .

Let's first take a look at fetching some previously issued commands using vi . The examples in this section use vi functionality that is described in both the vi chapter and on the vi quick reference card. The k, j, G , and search commands in this section operate in the same manner on the command line as they would if you were using vi to edit a file.

Pressing the escape key and a command allows you to perform various functions in the ksh . The following example shows producing the history list and issuing escape k to recall the previous command:

 martyp $  history  125     man fc 126     set  more 127      exit 128     history 129     k 130     env  more 131     set  more 132     more .profile 133     more .profile  grep rof 134     more .profile  grep vi 135     more /etc/profile  grep vi 136     set grep edit 137     set  grep vi 138     env  grep vi 139     history 140     who martyp $  history  

Issuing escape k recalled the last command issued, in this case the who command at line 140. Each time you press k , the preceding ksh command is fetched . This is the same as pressing escape and the - (hyphen) key. You can specify the number of commands you wish to go back in the history list with escape n k , where n is the number of commands you want to go back in the history list. The following example shows issuing escape 5k to fetch the fifth command back in the history list:

 graphics/grepa_icon.gif martyp $  history  125     man fc 126     set  more 127      exit 128     history 129     k 130     env  more 131     set  more 132     more .profile 133     more .profile  grep rof 134     more .profile  grep vi 135     more /etc/profile  grep vi 136     set grep edit 137     set  grep vi 138     env  grep vi 139     history 140     who martyp $  set   grep edit  

Issuing escape 5k fetched the fifth command back in the history list at line 136 . This is the same as having issued escape 5- .

You can also move forward in the history list, using j in the same way we used k to move back in the history list. Let's issue escape 5k to move back five commands in the history list to line 136 , and then we can use escape 3j to move forward three commands to line 139 , as shown in the following example:

 martyp $  history  125     man fc 126     set  more 127      exit 128     history 129     k 130     env  more 131     set  more 132     more .profile 133     more .profile  grep rof 134     more .profile  grep vi 135     more /etc/profile  grep vi 136     set grep edit 137     set  grep vi 138     env  grep vi 139     history 140     history martyp $  who  

Issuing escape 3j moved us forward to line 139 , which is the same as having issued escape 3- .

We can also go back to the oldest command in the history list with escape G . You can go back to a specific command number from the history list with escape n G , where n is a specific command number from the history file. The following example shows issuing escape 126G to go back to line 126 from the history list:

 martyp $  history  125     man fc 126     set  more 127      exit 128     history 129     k 130     env  more 131     set  more 132     more .profile 133     more .profile  grep rof 134     more .profile  grep vi 135     more /etc/profile  grep vi 136     set grep edit 137     set  grep vi 138     env  grep vi 139     history 140     who martyp $  set  more  

You can also recall lines from the history list based on searches. If, for instance, you want to recall the most recently issued command from the history list that has in it profile , you would issue /profile , which is the slash character followed by profile , to get the result shown in the following example:

 martyp $  history  125     man fc 126     set  more 127      exit 128     history 129     k 130     env  more 131     set  more 132     more .profile 133     more .profile  grep rof 134     more .profile  grep vi 135     more /etc/profile  grep vi 136     set grep edit 137     set  grep vi 138     env  grep vi 139     history 140     who martyp $  more /etc/profile  grep vi  

Searching for the most recent occurrence of profile produces line 135 . Many of the other searches in vi work at the command line. The vi chapter and vi quick reference card have more searching commands that you may want to try at the command line.

Editing on the Command Line Using vi Directives

After you have "fetched" the command you wish to edit or you have entered a command that needs editing, you can use your vi directives to make modifications on the command line.

The ksh puts you in input mode immediately upon fetching a command from the history list. This approach is the converse of the vi program that you use to edit files, which puts you in control mode by default. After you have fetched a command from the history list, you must press escape in order to move into control mode when using vi in ksh .

Let's now perform some simple modifications to commands we have fetched from the history list. We recall line number 286 from the history list with the sequence escape 286G . After recalling this command, we insert cat at the beginning of the command with i cat. i is for insert text to the left of the current cursor position. The following example shows the result of both the fetch of line 286 and inserting cat :

 martyp $  history  285     history 286     more /etc/profile  grep vi 287     who 288     whoami 289     who 290     ls -al 291     alias 292     pwd 293     ls -al /home 294     cat .profile 295     history 296     vi .profile 297     cat /etc/passwd 298     cat /etc/passwd  grep donna 299     pwd 300     history martyp $  cat more /etc/profile  grep vi  

You can see that i cat inserted cat at the very beginning of the line.

We can again recall line 286 and use A to append text to the very end of the line, as shown in the following example:

 martyp $  history  285     history 286     more /etc/profile  grep vi 287     who 288     whoami 289     who 290     ls -al 291     alias 292     pwd 293     ls -al /home 294     cat .profile 295     history 296     vi .profile 297     cat /etc/passwd 298     cat /etc/passwd  grep donna 299     pwd 300     history martyp $  more /etc/profile  grep vieditor  
graphics/grepa_icon.gif

In this example, we used the sequence A editor to insert the word editor at the very end of the command line we had recalled.

We can recall this line and change more at the beginning of the line to cat by issuing the sequence cw cat , as shown in the following example:

 martyp $  history  285     history 286     more /etc/profile  grep vi 287     who 288     whoami 289     who 290     ls -al 291     alias 292     pwd 293     ls -al /home 294     cat .profile 295     history 296     vi .profile 297     cat /etc/passwd 298     cat /etc/passwd  grep donna 299     pwd 300     history martyp $  cat /etc/profile  grep vi  

This changes more to cat on the command line.

To delete the word more without replacing it, we fetch line 286 and issue dw , as shown in the following example:

 martyp $  history  285     history 286     more /etc/profile  grep vi 287     who 288     whoami 289     who 290     ls -al 291     alias 292     pwd 293     ls -al /home 294     cat .profile 295     history 296     vi .profile 297     cat /etc/passwd 298     cat /etc/passwd  grep donna 299     pwd 300     history martyp $  /etc/profile  grep vi  

If we are unhappy with the most recent command issued, we can undo the command by issuing u , which undoes the dw we used to remove more on the command line, as shown in the following example:

 graphics/grepa_icon.gif martyp $  history  285     history 286     more /etc/profile  grep vi 287     who 288     whoami 289     who 290     ls -al 291     alias 292     pwd 293     ls -al /home 294     cat .profile 295     history 296     vi .profile 297     cat /etc/passwd 298     cat /etc/passwd  grep donna 299     pwd 300     history martyp $  more /etc/profile  grep vi  

Issuing u puts back the more that we had removed with dw .

You may want to try using both of the vi commands I have covered here, as well as other commands to add, delete, change, search and replace, copy, and undo at the command line.

Aliases in KornShell

An alias is a name that you select for a frequently used command or series of commands. Many aliases are predefined for you.

The alias command, without any arguments, lists all aliases. This list includes both preset aliases as well as those you have set. The following command shows the preset aliases on the system on which I am working:

 martyp $  alias  autoload='typeset -fu' command='command ' functions='typeset -f' history='fc -l' hyper1=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc1;export HHLIC' hyper36=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc36;export HHLIC' hyper83=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc83;export HHLIC' hyper95=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc95;export HHLIC' integer='typeset -i' local=typeset nohup='nohup ' r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' martyp $ 

Many preset aliases are shown as a result of typing the alias command without any options.

Many of these aliases are related to somewhat advanced use of the KornShell, such as job control. Others are useful to you right away. The history alias, for instance, lists the commands in the .sh_history file and precedes each entry by a line number. The r alias allows you to re-run the the last command that appears in the history list.

You are not limited to using only preset aliases. You can set your own aliases. The following example shows setting an alias, producing a list of aliases to see whether indeed our new alias has been set, and then running our alias:

 martyp $  alias ls="ls -al"  martyp $  alias  autoload='typeset -fu' command='command ' functions='typeset -f' history='fc -l' hyper1=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc1;export HHLIC' hyper36=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc36;export HHLIC' hyper83=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc83;export HHLIC' hyper95=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc95;export HHLIC' integer='typeset -i' local=typeset ls='ls -al' nohup='nohup ' r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' martyp $  ls  total 26 drwxr-xr-x   2 martyp   staff        512 Mar 15 11:37. drwxrwxr-x   4 root     sys          512 Mar  4 09:24 .. -rw-r--r--   1 martyp   staff        124 Mar 15 11:36 .cshrc -rw-r--r--   1 martyp   staff        562 Mar  4 09:24 .profile -rw-------   1 martyp   staff       9058 Apr 10 06:58 .sh_history martyp $ 

The first command set an alias that executes ls -al whenever we type ls . I issued the alias command to see whether indeed the new alias would appear in the list of aliases. It appears right after local and right before nohup in the alphabetical list of aliases. The final command shows running ls , which produces the same listing that you would receive from running the ls -al command.

You don't have to keep an alias for the duration of your session after having set it. If you don't like an alias, you can use the unalias command to remove an alias.

To see unalias work, let's again produce a list of aliases, use unalias to unset the history alias, run the history command to see whether indeed it has been removed, and then run the fc -l command to which the history alias was mapped:

 martyp $  alias  autoload='typeset -fu' command='command ' functions='typeset -f' history='fc -l' hyper1=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc1;export HHLIC' hyper36=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc36;export HHLIC' hyper83=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc83;export HHLIC' hyper95=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc95;export HHLIC' integer='typeset -i' local=typeset nohup='nohup ' r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' martyp $  unalias history  martyp $  history  ksh: history:  not found martyp $  fc -l  131     ps 132     ls -alF 133     ls -al 134     alias ls="ls -al" 135     alias 136     ls 137     alias 138     unalias ls 139     ls 140     ls -al 141     alias 142     history 143     alias 144     unalias history 145     history 146     fc -l martyp $ 

When we unalias history and then run history, ksh is unable to find it and produces the message history: not found . When we run fc -l , a list of the most recently issued commands with their corresponding numbers is produced. This makes it clear that when you run the history alias, you are actually running the fc -l command.

Command and Path Completion

ksh sometimes knows what you're thinking. You can type part of a command or pathname and ksh can complete the remainder for you. You can type part of a command or pathname and press the escape key to complete the command. If, for instance, you wish to issue the uname command to view the current system run level but can't remember the full command, you can type "un" and escape, followed by the "=" key, and the command is completed for you. In the following example, we'll change to the /sbin directory, list its contents, and then type un escape = :

 martyp $  cd /sbin  martyp $  ls -al  total 11704 drwxrwxr-x   2 root     sys          512 Nov 27 14:55. drwxr-xr-x  31 root     root        1024 Apr 19 03:24 .. -r-xr-xr-x   1 bin      bin       200356 Sep  1  1998 autopush lrwxrwxrwx   1 root     root          21 Nov 27 14:55 bpgetfile -> ../usr/sbin/e -r-xr-xr-x   1 bin      bin       470436 Sep  1  1998 dhcpagent -r-xr-xr-x   1 bin      bin       433064 Sep  1  1998 dhcpinfo -r-xr-xr-x   1 bin      bin       253664 Sep  1  1998 fdisk -r-xr-xr-x   1 bin      bin       762816 Sep  1  1998 hostconfig -r-xr-xr-x   1 bin      bin       535900 Sep  1  1998 ifconfig -r-xr-xr-x   1 root     sys       516484 Sep  1  1998 init -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 jsh -r-xr-xr-x   1 bin      bin       224596 Sep  1  1998 mount -r-xr-xr-x   1 root     sys         6935 Jan  1  1970 mountall -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc0 -rwxr--r--   1 root     sys         2905 Jan  1  1970 rc1 -rwxr--r--   1 root     sys         2491 Jan  1  1970 rc2 -rwxr--r--   1 root     sys         1948 Jan  1  1970 rc3 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc5 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc6 -rwxr--r--   1 root     sys         9412 Jan  1  1970 rcS -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 sh -r-xr-xr-x   1 bin      bin       195300 Sep  1  1998 soconfig lrwxrwxrwx   1 root     root          13 Nov 27 14:40 su -> ../usr/bin/su -r-xr-xr-x   1 root     sys       473808 Sep  1  1998 su.static -r-xr-xr-x   1 root     bin       288544 Sep  1  1998 sulogin -rwxr--r--   1 root     sys         3138 Jan  1  1970 swapadd -r-xr-xr-x   1 bin      bin        29736 Sep  1  1998 sync -r-xr-xr-x   1 root     sys       435004 Sep  1  1998 uadmin -r-xr-xr-x   1 bin      bin       213408 Sep  1  1998 umount -r-xr-xr-x   1 root     sys         3292 Jan  1  1970 umountall -r-xr-xr-x   1 bin      bin       193152 Sep  1  1998 uname martyp $  un  ;typed  un   escape   =  1) uname martyp $  un  

ksh determined that the only command that starts with "un" is uname . The uname command was listed and un was again put at the command prompt for me. You can't see the escape = I typed after the first "un," so I made a comment to the side showing the full command.

Rather than list all files starting with "un," you can replace the current word with all files that match by typing un escape *, as shown in the following example:

 martyp $  cd /sbin  martyp $  ls -al  total 11704 drwxrwxr-x   2 root     sys          512 Nov 27 14:55. drwxr-xr-x  31 root     root        1024 Apr 19 03:24 .. -r-xr-xr-x   1 bin      bin       200356 Sep  1  1998 autopush lrwxrwxrwx   1 root     root          21 Nov 27 14:55 bpgetfile -> ../usr/sbin/e -r-xr-xr-x   1 bin      bin       470436 Sep  1  1998 dhcpagent -r-xr-xr-x   1 bin      bin       433064 Sep  1  1998 dhcpinfo -r-xr-xr-x   1 bin      bin       253664 Sep  1  1998 fdisk -r-xr-xr-x   1 bin      bin       762816 Sep  1  1998 hostconfig -r-xr-xr-x   1 bin      bin       535900 Sep  1  1998 ifconfig -r-xr-xr-x   1 root     sys       516484 Sep  1  1998 init -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 jsh -r-xr-xr-x   1 bin      bin       224596 Sep  1  1998 mount -r-xr-xr-x   1 root     sys         6935 Jan  1  1970 mountall -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc0 -rwxr--r--   1 root     sys         2905 Jan  1  1970 rc1 -rwxr--r--   1 root     sys         2491 Jan  1  1970 rc2 -rwxr--r--   1 root     sys         1948 Jan  1  1970 rc3 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc5 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc6 -rwxr--r--   1 root     sys         9412 Jan  1  1970 rcS -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 sh -r-xr-xr-x   1 bin      bin       195300 Sep  1  1998 soconfig lrwxrwxrwx   1 root     root          13 Nov 27 14:40 su -> ../usr/bin/su -r-xr-xr-x   1 root     sys       473808 Sep  1  1998 su.static -r-xr-xr-x   1 root     bin       288544 Sep  1  1998 sulogin -rwxr--r--   1 root     sys         3138 Jan  1  1970 swapadd -r-xr-xr-x   1 bin      bin        29736 Sep  1  1998 sync -r-xr-xr-x   1 root     sys       435004 Sep  1  1998 uadmin -r-xr-xr-x   1 bin      bin       213408 Sep  1  1998 umount -r-xr-xr-x   1 root     sys         3292 Jan  1  1970 umountall -r-xr-xr-x   1 bin      bin       193152 Sep  1  1998 uname martyp $  uname  ;typed  un   escape   *  

You can see in this example that uname is replaced right at the prompt with the only command that matched un escape * .

The next example shows using um escape = to get a list of all files that start with "um," then using um escape * to get all files matched to "um," and finally, using um escape \ to replace the current word with the first file name that starts with "um":

 martyp $  ls -al  total 11704 drwxrwxr-x   2 root     sys          512 Nov 27 14:55. drwxr-xr-x  31 root     root        1024 Apr 19 03:24 .. -r-xr-xr-x   1 bin      bin       200356 Sep  1  1998 autopush lrwxrwxrwx   1 root     root          21 Nov 27 14:55 bpgetfile -> ../usr/sbin/e -r-xr-xr-x   1 bin      bin       470436 Sep  1  1998 dhcpagent -r-xr-xr-x   1 bin      bin       433064 Sep  1  1998 dhcpinfo -r-xr-xr-x   1 bin      bin       253664 Sep  1  1998 fdisk -r-xr-xr-x   1 bin      bin       762816 Sep  1  1998 hostconfig -r-xr-xr-x   1 bin      bin       535900 Sep  1  1998 ifconfig -r-xr-xr-x   1 root     sys       516484 Sep  1  1998 init -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 jsh -r-xr-xr-x   1 bin      bin       224596 Sep  1  1998 mount -r-xr-xr-x   1 root     sys         6935 Jan  1  1970 mountall -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc0 -rwxr--r--   1 root     sys         2905 Jan  1  1970 rc1 -rwxr--r--   1 root     sys         2491 Jan  1  1970 rc2 -rwxr--r--   1 root     sys         1948 Jan  1  1970 rc3 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc5 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc6 -rwxr--r--   1 root     sys         9412 Jan  1  1970 rcS -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 sh -r-xr-xr-x   1 bin      bin       195300 Sep  1  1998 soconfig lrwxrwxrwx   1 root     root          13 Nov 27 14:40 su -> ../usr/bin/su -r-xr-xr-x   1 root     sys       473808 Sep  1  1998 su.static -r-xr-xr-x   1 root     bin       288544 Sep  1  1998 sulogin -rwxr--r--   1 root     sys         3138 Jan  1  1970 swapadd -r-xr-xr-x   1 bin      bin        29736 Sep  1  1998 sync -r-xr-xr-x   1 root     sys       435004 Sep  1  1998 uadmin -r-xr-xr-x   1 bin      bin       213408 Sep  1  1998 umount -r-xr-xr-x   1 root     sys         3292 Jan  1  1970 umountall -r-xr-xr-x   1 bin      bin       193152 Sep  1  1998 uname martyp $  um  ;typed  um   escape   =  1) umount 2) umountall martyp $  umount umountall  ;typed  um   escape   *  martyp $  umount  ;typed  um   escape   \  

Let's now work with a command and arguments that will be file names . What if the characters you type are not unique, as they were with "un" in the /sbin directory? If the command or pathname is not unique, then ksh shows you the options for completing the command. The following example shows typing ls r escape = to get a list of commands that start with "r":

 martyp $  ls -al  total 11704 drwxrwxr-x   2 root     sys          512 Nov 27 14:55. drwxr-xr-x  31 root     root        1024 Apr 19 03:24 .. -r-xr-xr-x   1 bin      bin       200356 Sep  1  1998 autopush lrwxrwxrwx   1 root     root          21 Nov 27 14:55 bpgetfile -> ../usr/sbin/e -r-xr-xr-x   1 bin      bin       470436 Sep  1  1998 dhcpagent -r-xr-xr-x   1 bin      bin       433064 Sep  1  1998 dhcpinfo -r-xr-xr-x   1 bin      bin       253664 Sep  1  1998 fdisk -r-xr-xr-x   1 bin      bin       762816 Sep  1  1998 hostconfig -r-xr-xr-x   1 bin      bin       535900 Sep  1  1998 ifconfig -r-xr-xr-x   1 root     sys       516484 Sep  1  1998 init -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 jsh -r-xr-xr-x   1 bin      bin       224596 Sep  1  1998 mount -r-xr-xr-x   1 root     sys         6935 Jan  1  1970 mountall -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc0 -rwxr--r--   1 root     sys         2905 Jan  1  1970 rc1 -rwxr--r--   1 root     sys         2491 Jan  1  1970 rc2 -rwxr--r--   1 root     sys         1948 Jan  1  1970 rc3 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc5 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc6 -rwxr--r--   1 root     sys         9412 Jan  1  1970 rcS -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 sh -r-xr-xr-x   1 bin      bin       195300 Sep  1  1998 soconfig lrwxrwxrwx   1 root     root          13 Nov 27 14:40 su -> ../usr/bin/su -r-xr-xr-x   1 root     sys       473808 Sep  1  1998 su.static -r-xr-xr-x   1 root     bin       288544 Sep  1  1998 sulogin -rwxr--r--   1 root     sys         3138 Jan  1  1970 swapadd -r-xr-xr-x   1 bin      bin        29736 Sep  1  1998 sync -r-xr-xr-x   1 root     sys       435004 Sep  1  1998 uadmin -r-xr-xr-x   1 bin      bin       213408 Sep  1  1998 umount -r-xr-xr-x   1 root     sys         3292 Jan  1  1970 umountall -r-xr-xr-x   1 bin      bin       193152 Sep  1  1998 uname martyp $  ls r  ;typed  ls r   escape   =  1) rc0 2) rc1 3) rc2 4) rc3 5) rc5 6) rc6 7) rcS martyp $  ls r  

You can see from this example that typing ls -r escape = produced a list of seven files. Again, the ls r was placed for me at the next prompt. You can use the information left for you at the next prompt to perform additional ksh file name expansion. Let's again perform our ls r escape =, which produces the list of seven files beginning with r . Our next prompt will have ls r waiting for us, and this time we'll type escape *, which will produce a list of all seven files for us on the line:

 martyp $  ls -al  total 11704 drwxrwxr-x   2 root     sys          512 Nov 27 14:55. drwxr-xr-x  31 root     root        1024 Apr 19 03:24 .. -r-xr-xr-x   1 bin      bin       200356 Sep  1  1998 autopush lrwxrwxrwx   1 root     root          21 Nov 27 14:55 bpgetfile -> ../usr/sbin/e -r-xr-xr-x   1 bin      bin       470436 Sep  1  1998 dhcpagent -r-xr-xr-x   1 bin      bin       433064 Sep  1  1998 dhcpinfo -r-xr-xr-x   1 bin      bin       253664 Sep  1  1998 fdisk -r-xr-xr-x   1 bin      bin       762816 Sep  1  1998 hostconfig -r-xr-xr-x   1 bin      bin       535900 Sep  1  1998 ifconfig -r-xr-xr-x   1 root     sys       516484 Sep  1  1998 init -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 jsh -r-xr-xr-x   1 bin      bin       224596 Sep  1  1998 mount -r-xr-xr-x   1 root     sys         6935 Jan  1  1970 mountall -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc0 -rwxr--r--   1 root     sys         2905 Jan  1  1970 rc1 -rwxr--r--   1 root     sys         2491 Jan  1  1970 rc2 -rwxr--r--   1 root     sys         1948 Jan  1  1970 rc3 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc5 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc6 -rwxr--r--   1 root     sys         9412 Jan  1  1970 rcS -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 sh -r-xr-xr-x   1 bin      bin       195300 Sep  1  1998 soconfig lrwxrwxrwx   1 root     root          13 Nov 27 14:40 su -> ../usr/bin/su -r-xr-xr-x   1 root     sys       473808 Sep  1  1998 su.static -r-xr-xr-x   1 root     bin       288544 Sep  1  1998 sulogin -rwxr--r--   1 root     sys         3138 Jan  1  1970 swapadd -r-xr-xr-x   1 bin      bin        29736 Sep  1  1998 sync -r-xr-xr-x   1 root     sys       435004 Sep  1  1998 uadmin -r-xr-xr-x   1 bin      bin       213408 Sep  1  1998 umount -r-xr-xr-x   1 root     sys         3292 Jan  1  1970 umountall -r-xr-xr-x   1 bin      bin       193152 Sep  1  1998 uname martyp $  ls r  ;typed  ls r   escape   =  1) rc0 2) rc1 3) rc2 4) rc3 5) rc5 6) rc6 7) rcS martyp $  ls rc0 rc1 rc2 rc3 rc5 rc6 rcS  ;typed  escape   *   to get seven files  

escape * listed all seven files beginning with r and placed them on the command line.

In the next example we'll issue both the escape = and escape * . We'll then type ls escape _ ( underscore ), which puts the last word of the last command in the line, which is rcS:

 martyp $  ls -al  total 11704 drwxrwxr-x   2 root     sys          512 Nov 27 14:55. drwxr-xr-x  31 root     root        1024 Apr 19 03:24 .. -r-xr-xr-x   1 bin      bin       200356 Sep  1  1998 autopush lrwxrwxrwx   1 root     root          21 Nov 27 14:55 bpgetfile -> ../usr/sbin/e -r-xr-xr-x   1 bin      bin       470436 Sep  1  1998 dhcpagent -r-xr-xr-x   1 bin      bin       433064 Sep  1  1998 dhcpinfo -r-xr-xr-x   1 bin      bin       253664 Sep  1  1998 fdisk -r-xr-xr-x   1 bin      bin       762816 Sep  1  1998 hostconfig -r-xr-xr-x   1 bin      bin       535900 Sep  1  1998 ifconfig -r-xr-xr-x   1 root     sys       516484 Sep  1  1998 init -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 jsh -r-xr-xr-x   1 bin      bin       224596 Sep  1  1998 mount -r-xr-xr-x   1 root     sys         6935 Jan  1  1970 mountall -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc0 -rwxr--r--   1 root     sys         2905 Jan  1  1970 rc1 -rwxr--r--   1 root     sys         2491 Jan  1  1970 rc2 -rwxr--r--   1 root     sys         1948 Jan  1  1970 rc3 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc5 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc6 -rwxr--r--   1 root     sys         9412 Jan  1  1970 rcS -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 sh -r-xr-xr-x   1 bin      bin       195300 Sep  1  1998 soconfig lrwxrwxrwx   1 root     root          13 Nov 27 14:40 su -> ../usr/bin/su -r-xr-xr-x   1 root     sys       473808 Sep  1  1998 su.static -r-xr-xr-x   1 root     bin       288544 Sep  1  1998 sulogin -rwxr--r--   1 root     sys         3138 Jan  1  1970 swapadd -r-xr-xr-x   1 bin      bin        29736 Sep  1  1998 sync -r-xr-xr-x   1 root     sys       435004 Sep  1  1998 uadmin -r-xr-xr-x   1 bin      bin       213408 Sep  1  1998 umount -r-xr-xr-x   1 root     sys         3292 Jan  1  1970 umountall -r-xr-xr-x   1 bin      bin       193152 Sep  1  1998 uname martyp $  ls r  ;typed  ls r   escape   =  1) rc0 2) rc1 3) rc2 4) rc3 5) rc5 6) rc6 7) rcS martyp $  ls rc0 rc1 rc2 rc3 rc5 rc6 rcS  ;typed  escape   *  to get seven files rc0  rc1  rc2  rc3  rc5  rc6  rcS martyp $  ls  rcS  ;typed  ls   escape   _  to get last word rcS martyp $ 

Now that we've seen how to get the last of the words to appear on the command line with escape _, how about the third word of the last command? You can specify the third word by typing escape 3_ or substitute for the "3" for any of the words on the last command line. The following example shows listing the third word of the last command:

 martyp $  ls -al  total 11704 drwxrwxr-x   2 root     sys          512 Nov 27 14:55. drwxr-xr-x  31 root     root        1024 Apr 19 03:24 .. -r-xr-xr-x   1 bin      bin       200356 Sep  1  1998 autopush lrwxrwxrwx   1 root     root          21 Nov 27 14:55 bpgetfile -> ../usr/sbin/e -r-xr-xr-x   1 bin      bin       470436 Sep  1  1998 dhcpagent -r-xr-xr-x   1 bin      bin       433064 Sep  1  1998 dhcpinfo -r-xr-xr-x   1 bin      bin       253664 Sep  1  1998 fdisk -r-xr-xr-x   1 bin      bin       762816 Sep  1  1998 hostconfig -r-xr-xr-x   1 bin      bin       535900 Sep  1  1998 ifconfig -r-xr-xr-x   1 root     sys       516484 Sep  1  1998 init -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 jsh -r-xr-xr-x   1 bin      bin       224596 Sep  1  1998 mount -r-xr-xr-x   1 root     sys         6935 Jan  1  1970 mountall -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc0 -rwxr--r--   1 root     sys         2905 Jan  1  1970 rc1 -rwxr--r--   1 root     sys         2491 Jan  1  1970 rc2 -rwxr--r--   1 root     sys         1948 Jan  1  1970 rc3 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc5 -rwxr--r--   3 root     sys         2689 Jan  1  1970 rc6 -rwxr--r--   1 root     sys         9412 Jan  1  1970 rcS -r-xr-xr-x   2 bin      root      257444 Sep  1  1998 sh -r-xr-xr-x   1 bin      bin       195300 Sep  1  1998 soconfig lrwxrwxrwx   1 root     root          13 Nov 27 14:40 su -> ../usr/bin/su -r-xr-xr-x   1 root     sys       473808 Sep  1  1998 su.static -r-xr-xr-x   1 root     bin       288544 Sep  1  1998 sulogin -rwxr--r--   1 root     sys         3138 Jan  1  1970 swapadd -r-xr-xr-x   1 bin      bin        29736 Sep  1  1998 sync -r-xr-xr-x   1 root     sys       435004 Sep  1  1998 uadmin -r-xr-xr-x   1 bin      bin       213408 Sep  1  1998 umount -r-xr-xr-x   1 root     sys         3292 Jan  1  1970 umountall -r-xr-xr-x   1 bin      bin       193152 Sep  1  1998 uname martyp $  ls r  ;typed  ls r   escape   =  1) rc0 2) rc1 3) rc2 4) rc3 5) rc5 6) rc6 7) rcS martyp $  ls rc0 rc1 rc2 rc3 rc5 rc6 rcS  ;typed  escape   *  to get seven files rc0  rc1  rc2  rc3  rc5  rc6  rcS martyp $  ls  rc1  ;typed  ls   escape   3_  to get third word 

Because the previous command included the ls command, the third word is not rc2 but rc1 , because ls was the first entry in the previous command.

The Table 27-1 summarizes the command and path completion used in the previous examples:

Table 27-1. Command and Path Completion in ksh

Word or Command

(type escape before each)

Result

word escape =

Displays a numbered list of file names beginning with word .

word escape *

Replaces word with all files matched.

word escape \

Replaces word with the first file name that starts with word .

command word escape =

Displays a numbered list of file names beginning with word .

command word escape *

Replaces word with all files matched.

command word escape _

Inserts the last word of the last command at the cursor position.

command word escape _3

Inserts the third word of the last command at the cursor position.

File Name Expansion

In your general activities working with ksh , you have to perform a lot of file-name-related work, including crafting shell scripts that deal with file names. An overview of file name expansion is useful to ensure that you're comfortable with this topic before you start writing shell scripts.

Table 27-2 lists some common filename expansion and pattern matching commands:

Table 27-2. File Name Expansion and Pattern Matching

Character(s)

Example

Description

*

1) ls *.c

Match zero or more characters

?

2) ls conf.?

Match any single character

[list]

3) ls conf.[co]

Match any character in list

[lower-upper]

4) ls libdd.9873[5-6].sl

Match any character in range

str{str1,str2,str3,...}

5) ls ux*.{700,300}

Expand str with contents of {}

~

6) ls -a ~

Home directory

~username

7) ls -a ~gene

Home directory of username

The following are more detailed descriptions of the examples shown in Table 27-2:

  1. To list all files in a directory that end in ".c," you could do the following:


    $   ls  *.c
                   conf.  SAM.c  conf.c

  2. To find all the files in a directory named "conf" with an extension of one character, you could do the following:


    $   ls  conf.?
                 conf.c  conf.o  conf.1

  3. To list all the files in a directory named "conf" with only the extension "c" or "o," you could do the following:


    $   ls  conf.{co}
                 conf.c  conf.o

  4. To list files with similar names but with a specific field that covers a range, you could do the following:


    $   ls  libdd9873[5-6].sl
                   libdd98735.sl  libdd98736.sl

  5. To list files that start with "ux" and have the extension "300" or "700," you could do the following:


    $   ls  ux*.{700,300}
                 uxbootlf.700  uxinstfs.300

  6. To list the files in your home directory, you could use ~:


    $   ls  -a  ~
                 .        .cshrc.org  .login        .shrc.org
                 ..      .exrc        .login.org        .cshrc
                 .history

  7. To list the files in the home directory of a user, you can do the following:


    $   ls  -a  ~gene
                 .            .history      splinedat  under.des
                 ..          .login        trail.txt  xtra.part
                 .chsrc      .login.org  ESP-File
                 .cshrc.org  .profile  Mail
                 .exrc        .shrc.org  opt

Many of these techniques are useful when working with ksh and writing shell scripts, so you want to become familiar with file name expansion.

Redirection (I/O Redirection)

UNIX is set up such that commands usually take their input from the keyboard, often called standard input, and usually send output to the screen, often called standard output . Commands also send error information to the screen. You do not always want input to come from standard input and output and errors to go to standard output. You are given a lot of control to override these defaults. This is called redirection . Table 27-3 shows many common forms of redirection.

As shown in Table 27-3, to redirect the output of a command from standard output to a file, you use ">". This works almost all of the time. If you have an environment variable called noclobber set, then redirecting to an existing file does not work (we'll cover environment variables shortly). The noclobber does not permit redirection to write over an existing file. If you try to write over an existing file, such as /tmp/processes below, you receive a message that the file exists:

 #  ps  -ef  > /tmp/processes  /tmp/processes:  File exists 

You can, however, use a "!" with redirection to force a file to be overwritten. Using ">!" forces a file to be overwritten, and ">>!" forces the output to be appended to the end of an existing file. Examples of these are shown in Table 27-3.

Table 27-3. Commonly Used Redirection Forms

Command or Assignment

Example

Description

<

wc -l < .login

Standard input redirection:

execute wc (word count) and list number of lines ( -l ) in .login

>

ps -ef > /tmp/processes

Standard output redirection:

execute ps and send output to file /tmp/processes

>>

ps -ef >> /tmp/processes

Append standard output:

execute ps and append output to the end of file /tmp/processes

>!

ps -ef >! /tmp/processes

Standard output redirection and override noclobber :

write over /tmp/processes even if it exists

>>!

ps -ef >>! /tmp/processes

Append standard output and override noclobber :

append to the end of /tmp/processes

(pipe)

ps wc -l

Run ps and use the result as input to wc

- standard input

   

1 - standard output

   

2 - standard error

cat program 2> errors

cat the file program to standard output and redirect errors to the file errors

 

cat program 2>> errors

cat the file program to standard output and append errors to the file errors

 

find / -name '*.c' -print > cprograms 2>errors

find all files on the system ending in .c , place the list of files in cprograms in the current working directory, and send all errors (file descriptor 2) to the file errors in current working directory

 

find / -name '*.c' -print > cprograms 2>&1

find all files on the system ending in .c , place the list of files in cprograms in the current working directory, and send all errors (file descriptor 2) to same place as file descriptor 1 ( cprograms )

Environment Variables

An environment variable is a name associated with a string. The name is the variable and the string is its value. Environment variables are also available to sub-shells or processes spawned by the shell. In most cases, you see environment variables capitalized, which is the convention on most systems.

When you issue a command on the system, you usually enter a relative pathname, not an absolute pathname. The command you issue is found because the PATH variable points to the location of directories where commands are located. Without this PATH variable, you would have to type the absolute pathname of every command you issue. When you issue a command, the shell searches the directories listed in the PATH variable in the order in which they are listed. A good way to see many of the environment variables you have set is with the env command as shown below:

 martyp $  env  _=/usr/bin/env MANPATH=:/opt/local/ptc/sysadmin/scripts:/opt/local/ptc/man:/opt/local/altrasofn _INIT_UTS_RELEASE=5.7 HZ=100 _INIT_UTS_MACHINE=sun4m EPC=true PATH=/usr/bin:/usr/ucb:/etc:. WEB_SERVER=sioux.rose.hp.com _INIT_UTS_VERSION=Generic MODEL=SPARCstation-10 OS_REV=5.7 EDITOR=vi _INIT_RUN_NPREV=0 CLASSPATH=.:/usr/java/lib: LOGNAME=martyp _INIT_UTS_NODENAME=sunsys _INIT_UTS_ISA=sparc MAIL=/var/mail/martyp ERASE=^H OS=solaris PS1=$PWD $LOGNAME $TOKEN _INIT_PREV_LEVEL=S HOST=sunsys TESTEXPERT_HOME=/opt/local/svn/te33 TA_HOME=/opt/local/platinum/solaris2/testadvise MA_HOME=/opt/local/platinum/solaris2/memadvise CL_LICENSE_FILE=/opt/local/CenterLine/configs/license.dat SHELL=/bin/ksh PROFILE_DIR=/opt/local/ptc/sysadmin/profile.d OSTYPE=solaris2 HOME=/home/martyp _INIT_UTS_SYSNAME=SunOS TERM=vt100 LD_LIBRARY_PATH=:/opt/local/parasoft/lib.solaris MWHOME=/opt/local/mainsoft/mainwin/mw FMHOME=/opt/local/adobe/frame PWD=/home/martyp TZ=US/Pacific _INIT_RUN_LEVEL=3 CLEARCASE_BLD_UMASK=02 _INIT_UTS_PLATFORM=SUNW,SPARCstation-10 martyp $ 

As you can see, other environment variables in addition to PATH make working on your UNIX system easier. You may want to issue other commmands related to ksh variables. Table 27-4 summarizes some ksh -related variable commands you may want to issue on your system.

Table 27-4. ksh -Related Variable Commands

Command

Description

env

Lists all environment variables (exported). These variables are normally uppercase and passed to child processes.

set

Prints all local and exported set variables.

set -o

Lists all built-in variables that are set to on or off .

typeset

Displays all variables and associated attributes, functions, and integers.

typeset +

Displays only the names of variables.

You may want to try all these commands on your system to see what variables have been set for you.

If you want to know the value of a specific environment variable, you could use the echo command to see its value, as shown below for the environment variable HOME :

 martyp $  echo $HOME  /home/martyp 

Similarly, to view the operating system type on this specific computer, you could issue the following command:

 martyp $  echo $OSTYPE  solaris2 

The "$" preceding the environment variable name specifies that the value of the variable be sent to standard output. In this case, the value of the environment variable HOME is /home/martyp , which means that the current user has a home directory of /home/martyp .

You can define your own environment variables in ksh with the following syntax:

 export  NAME=value  

Many users like to customize the ksh prompts. Most systems provide four ksh prompts by default. You can normally modify the first two prompts. The first, called PS1 , is the primary prompt. The second, called PS2 , appears after you have partially typed a command and pressed enter . PS1 is normally set to a $ and PS2 to >, by default.

The following example sets PS1 to our home directory, a space, the current history number, a space, and dollar sign:

 P  S1="`pwd` ! $ "  

We'll leave the default for PS2 as > . The following sequence shows issuing a command at our new PS1 prompt and the default PS2 prompt:

 /home/martyp 187 $  print "This is new PS1  >  but default PS2"  This is new PS1 but default PS2 /home/martyp 188 $ 

This example shows the new PS1 , including the history entry incrementing from 187 to 188 , and the default PS2 when the incomplete print command was issued.

You can also append to the end of an existing variable with the following format:

 export  NAME="$NAME:appended_information"  

To add /home/martyp/programs to the existing PATH environment variable, for instance, you issue the following command:

  export PATH="$PATH:/home/martyp/programs"  

This appends the path /home/martyp/programs to the environment variable PATH .

A great deal of flexibility is available when working with ksh . You should view all your variables and update those that make your job easier. Some customization, such as updating PS1 and your PATH , can also make your job easier.

Background Jobs and Job Control

When you run a command, as we have done so far in many examples, you don't get back the prompt until the command has completed. These commands have been run in the foreground. Some commands can take a long time to complete, in which case, you'll be waiting a long time for the prompt to return. As an alternative to waiting for the prompt to return, you can run the command in the background, meaning that it is running behind the scenes while you perform other work. Because UNIX is multi-tasking it is happy to run many commands in the background and still provide you with a prompt to issue yet more commands.

In order to run a command in the background, you simply add an ampersand (&) to the end of the command line. When you follow your command with an ampersand, the command is run in the background and the prompt is immediately returned.

Let's now run some commands on our Solaris system. We'll first run a command to find all of the files in /usr that end in ".c," which takes some time to complete. We'll preface the find string with the time command so that we know how long the command takes to complete:

 graphics/finda_icon.gif martyp $  time find /usr -name *.c  .              .              . /usr/demo/link_audit/src/dumpbind.c /usr/demo/link_audit/src/env.c /usr/demo/link_audit/src/hash.c /usr/demo/link_audit/src/perfcnt.c /usr/demo/link_audit/src/symbindrep.c /usr/demo/link_audit/src/truss.c /usr/demo/link_audit/src/who.c find: cannot read dir /usr/aset: Permission denied real    1m21.04s user    0m1.51s sys     0m12.67s 

This commad took roughly one minute and 21 seconds to complete. Because it was run in the foreground we were unable to issue any other commands while it was running, because we had to wait for the prompt to return.

An alternative to running the command in the foreground is to issue the command followed by an ampersand, in which case the job runs in the background and the prompt returns immediately, as shown in the following example:

 martyp $  time find /usr -name *.c > cprogs 2>&1 &  [3]     16279 martyp $ real    2m10.20s user    0m1.31s sys     0m8.62s 

The result of running this command in the background produces a job number in brackets and the process id, or PID, as the second number. All the outputs of this command, including errors, are written to the file cprogs . The prompt was immediately returned after we issued the command, and after it completed, the output of time was sent to the screen. We could have begun issuing additional commands immediately after issuing the command in the background.

You have control over both foreground jobs and background jobs. To suspend a foreground job, you type the "control" and "z" keys simultaneously , as shown in the following example:

 graphics/finda_icon.gif martyp $  find /usr -name *.c  /usr/openwin/share/include/X11/Xaw/Template.c /usr/openwin/share/src/dig_samples/DnD/main.c /usr/openwin/share/src/dig_samples/DnD/owner.c /usr/openwin/share/src/dig_samples/DnD/requestor.c /usr/openwin/share/src/dig_samples/Tooltalk/olit_tt.c /usr/openwin/share/src/dig_samples/Tooltalk/tt_callbacks.c /usr/openwin/share/src/dig_samples/Tooltalk/tt_code.c /usr/openwin/share/src/dig_samples/ce1/ce_map1.c /usr/openwin/share/src/dig_samples/ce2/ce_simple.c /usr/openwin/share/src/dig_samples/dnd_olit/olitdnd.c /usr/openwin/share/src/dig_samples/dnd_xview1/xview_dnd.c /usr/openwin/share/src/dig_samples/dnd_xview2/ xview_dnd2.c /usr/openwin/share/src/dig_samples/selection_olit/olit_sel.c /usr/openwin/share/src/dig_samples/tooltalk_simple/ttsend.c /usr/openwin/share/src/olit/oldials/oldials.c /usr/openwin/share/src/olit/olitbook/ch10/draw.c ^Z[3] + Stopped (SIGTSTP)        find /usr -name *.c 

After ctrl-z is pressed, the find command is interrupted at the point at which you type ctrl-z. The command is suspended at this point, and you are shown the job number, in this case "3," and its status is listed as "Stopped". This command has only been suspended ; it is not gone forever. You can start this process in the foreground with fg , or run it in the background with bg . Using bg runs the command as if you had followed it with an "&". It is started from the point at which you interrupted it. You do not have to supply a job number when you issue the fg or bg command, because the default is to perform the specified operation on the last job, which in this case is job number 3 .

Notice that in this example we have stopped job number 3 . This means that there are other jobs running with lower job numbers. You can use the jobs command to get a list of all jobs and their status. You can then control the jobs by issuing commands such as fg followed by a "%" and the job number to run the command in the foreground, or a bg followed by a "%" and the job number to run the command in the background. If you wish to terminate a job altogether, you can issue the kill command followed by a "%" and the job number.

In the process of creating the examples in this section, I have started and suspended many jobs. The following example shows listing all jobs with the jobs command, killing jobs 1 and 2 with kill , and running job 3 in the background:

 martyp $  jobs  [3] + Stopped (SIGTSTP) find /usr -name *.c [2] - Running         time find / -name gnu* > gnu 2>&1 & [1]   Running            time find / -name *.c > cprogs 2>&1 & martyp $  kill %1  [1]   Terminated         time find / -name *.c > cprogs 2>&1 & martyp $  kill %2  [2] - Terminated      time find / -name gnu* > gnu 2>&1 & martyp $  bg %3  [3]     find /usr -name *.c& martyp $ 

Notice that an ampersand was added to job 3 when we requested that it be run in the background. Killing jobs 1 and 2 and running job 3 in the background returns the prompt so that you can perform additional work.

umask and Permissions

An additional topic to cover related to ksh is file permissions and the way they relate to umask . This is important because you may write shell programs, and the permissions control the access that others will have to these programs. umask is used to specify permission settings for new files and directories.

Let's start with an example of a long listing of a file. We'll use ls -l in the following example:

 sys1 1:  ls -l script1  -rwxr-xr-x  1  marty  users  120 Jul 26 10:20 script1 

The access rights for this file are defined by the position of read (r), write (w), and execute (x) when the ls -l command is issued. Figure 27-1 shows the three groups of three access rights for this file:

Figure 27-1. Example of File Permissions

graphics/27fig01.gif

The owner of this file has read, write, and execute permissions on the file. The group to which the user belongs has read and execute permissions, and others also have read and execute permissions. The permissions on this file can be specified by the octal sum of each field, which is 755.

What happens if you craft a new shell script or any new file? What permission settings exist? You want to execute the shell script, so you need execute permission for the file. You can use umask to define the defaults for all your new files and directories.

By default, most systems start with a permission of 777 for directories and 666 for files. These mean that everyone has complete access to all directories you create and everyone has read and write access to all files you create. These defaults are modified with the value of umask .

You can view your umask in the following two ways:

 martyp $  umask  002 martyp $  umask -S  u=rwx,g=rwx,o=rx martyp $ 

The first example displays the octal value of umask , which we'll cover shortly, and the second example shows the symbolic value of umask .

The umask is used to disable access. You start with a umask and use the fields to disable some level of access. The umask command uses three octal fields. The fields are the sum of the access codes for user, group, and other as shown in Figure 27-2:

Figure 27-2. umask Fields

graphics/27fig02.gif

The complement of the umask field is " anded " with the default setting to change the umask . You can set umask by specifying its value. In our earlier example we viewed umask two different ways. To set the umask , you simply issue umask and the desired value. Setting umask to 022 , for example, removes write permissions of directories for "group" and "other," as shown in Figure 27-3:

Figure 27-3. umask Example

graphics/27fig03.gif

umask 022 changes the directory permissions to 755 in this example.

Similarly, a umask of 022 changes the default permission of 666 for files to 644, which would be read-only for group and other.

Change File Permissions with chmod

The chmod command is used to change the permissions on a file. Irrespective of what takes place with umask as just described, you can change a file's permissions at any time with chmod . You need to be the owner of the file or superuser to change a file's permissions with chmod in most cases. Let's start our discussion of chmod with the listing of the file sort :

 $  ls -l sort  -rwxr-x--x   1 marty     users     120 Jul 26 10:20 sort 

Figure 27-4 shows a breakdown of the permissions on sort :

Figure 27-4. Permissions of File sort

graphics/27fig04.gif

You have very little control over the type of file defined. You do, however, have a great deal of control over the permissions of this file if it belongs to you. The chmod command is used to change the permissions on a file or directory. If you are the owner of the file, you can have a field day changing the permissions on the file.

Two means exist by which you can change the permissions: symbolic and numeric. I focus first on the numeric mode, because the numbers involved are easy to manage, and I sometimes find that new UNIX users get hung up on the meanings of some of the symbols. I'll then cover the symbols and include the symbol meanings in the chmod summary.

First of all, what do I mean by numbers? Looking at the numbers for sort , we see permissions of 751: 7 for owner (hundred's position), 5 for group (ten's position), and 1 for other (one's position). Figure 27-5 helps with the meanings of the positions :

Figure 27-5. Numerical Permissions Summary

graphics/27fig05.jpg

Selecting the desired permissions for owner, group , and other, you use the chmod command to assign those permissions to a file or directory. Some of these permission possibilities are infrequently used, such as execute only, because you usually need to have read access to a file in order to execute it; however, I included all possibilities in Figure 27-5 for completeness. In addition to the permission mode bits shown in Figure 27-5, there are also miscellaneous mode bits, which you don't need to be concerned with at this time.

If you decide that you would like to add write permission of the file sort for group , and remove all permissions for other , you would simply execute the chmod command with the appropriate numeric value. The following set of commands first list the existing permissions for sort , next change the permissions on sort , and finally, list the new permissions on sort :

 $  ls -l sort  -rwxr-x--x   1 marty     users     120 Jul 26 10:20 sort $  chmod 770 sort  $  ls -l sort  -rwxrwx---   1 marty     users     120 Jul 26 10:20 sort 

The same set of commands to change the permissions using the symbolic mode would be:

 $  ls -l sort  -rwxr-x--x   1 marty     users     120 Jul 26 10:20 sort $  chmod g+w,o-x sort  $  ls -l sort  -rwxrwx---   1 marty     users     120 Jul 26 10:20 sort 

In symbolic mode, you issue the chmod command and specify who will be affected by the change [user (u), group (g), other (o), or all (a)], the operation you wish to perform [add (+), delete (-), or replace (=)], and the permission you wish to specify [read (r), write (w), or execute (x)]. In the previous example using symbolic mode, write (w) permission is being added (+) for group (g), and execute (x) permission is being removed (-) for other (o).

The following is a summary of some of the more commonly used symbols of chmod :

chmod - Change permissions of specified files using the following symbolic mode list.

Symbol of who is affected:

 

u

User is affected.

 

g

Group is affected.

 

o

Other is affected.

 

a

All users are affected.

Operation to perform:

 

+

Add permission.

 

-

Remove permission.

 

=

Replace permission.

Permission specified:

 

r

Read permission.

 

w

Write permission.

 

x

Execute permission.

 

u

Copy user permissions.

 

g

Copy group permissions.

 

o

Copy other permissions.



HP-UX 11i Systems Administration Handbook and Toolkit
HP-UX 11i Systems Administration Handbook and Toolkit (2nd Edition)
ISBN: 0131018833
EAN: 2147483647
Year: 2003
Pages: 301

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net