CONTENTS |
Most UNIX variants allow you to select among different shells. The shell is important to you as a user, because it is your window into the system. The many shells available on UNIX variants are similar, in that you use them to issue commands, control many aspects of your user environment, write command files and shell programs, and so on. Because you'll probably be spending a lot of time in your shell, you should develop an understanding of several different shells and see whether you develop a preference of one over another. A particular shell, such as Bash, does not vary much from one UNIX variant to another. The shells themselves, however, have some unique features. In general, I don't find that users strongly prefer one shell over another. All the shells are similar in functionality and enjoyable to use once you get to know them. Most UNIX variants allow your system administrator to select from among different shells when configuring users., so he or she usually has some flexibility concerning the shell that users run. In general, system administrators prefer users to use the same shell, making system administration easier in general. Most system administrators, however, are happy to grant a user request for a particular shell if indeed it is available on your system and you have a good reason to use it. I cover KornShell in this chapter. Bash is covered in the previous chapter and the C shell in the following chapter. 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. The ksh is the program which you run on your UNIX system 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 "Shell Programming Chapter."
Most of the examples in this chapter are from a Solaris system. You would probably find both your user setup and the operation of the KornShell on other systems similar to what is covered 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.
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.
ksh keeps a history list of the commands you have issued. If you wish to reissue a command or view a command which 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.
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 fact 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 present, 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 128 env 129 env | grep HIS 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 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.
You can reissue a command with the r commmand. 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 run the history 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 sustitutes.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.
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 wayyouedita 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 that 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 at 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 -(minus) key. You can specify the number of commands you wish to go back in the history list with escape nk, wheren 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:
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 nG, 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 information in them that you may want to try at the command line.
After you have "fetched" the command you wish to edit or 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
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:
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 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.
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 sets 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 a listing that you would receive from having run 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 runhistory, 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.
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 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 unescape=:
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 unescape= 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 unescape*, 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 unescape*
You can see in this example that uname is replaced right at the prompt with the only command that matched unescape*.
The next example shows using umescape= to get a list of all files that start with "um," then using umescape* to get all files matched to "um," and finally using umescape\ 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 umescape= 1) umount 2) umountall martyp $ umount umountall ;typed umescape* martyp $ umount ;typed umescape\
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 rescape= 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 rescape= 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 -rescape= 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 rescape=, 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 rescape= 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 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 b n 762816 Sep 1 998 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 b n bin 193152 Sep 1 1998 uname martyp $ ls r ;typed ls rescape= 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 lsescape_ 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 escape3_ 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 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 970 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 ro t 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 ys 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 rescape= 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 lsescape3_ 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 10-1 summarizes the command and path completion used in the previous examples.
Word or Command (type escape before each) | Result |
---|---|
wordescape= | Displays a numbered list of file names beginning with word. |
wordescape* | Replaces word with all files matched. |
wordescape\ | Replaces word with the first file name that starts with word. |
command wordescape= | Displays a numbered list of file names beginning with word. |
command wordescape* | Replaces word with all files matched. |
command wordescape_ | Inserts the last word of the last command at the cursor position. |
command wordescape_3 | Inserts the third word of the last command at the cursor position. |
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 10-2 lists some common filename 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 10-2:
To list all files in a directory that end in ".c," you could do the following:
$ ls *.c conf. SAM.c conf.c
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
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
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
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
To list the files in your home directory, you could use ~ as shown below:
$ ls -a ~ . .cshrc.org .login .shrc.org .. .exrc .login.org .cshrc .history
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.
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 10-3 shows many common forms of redirection.
As shown in Table 10-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 the Table 10-3.
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 outputto file/tmp/processes |
>> | ps -ef >> /tmp/processes | Append standard output: execute ps and append outputto theend offile /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 |
0 - 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) |
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 subshells 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 10-4 summarizes some ksh-related variable commands you may want to issue on your system.
Command | Description |
---|---|
env | Lists all environment variables (exported). These variables are normally uppercase and are 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 $ 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:
PS1="`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 in 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.
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:
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:
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/tt- send.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 a lower job number. 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 return the prompt so that you can perform additional work.
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 examples:
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 ll command is issued. Figure 10-1 shows the three groups of three access rights for this file.
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 10-2.
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 10-3:
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.
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 10-4 shows a breakdown of the permissions on sort.
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.
There are two means by which you can change the permissions: symbolic or 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 meaning 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 (hundreds position), 5 for group (tens position), and 1 for other (ones position). Figure 10-5 helps with the meanings of the positions.
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 10-5 for completeness. In addition to the permission mode bits shown in Figure 10-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.
|
The following are the HP-UX manual pages for many of the commands used in the chapter. Commands often differ among UNIX variants, so you may find differences in the options or other areas for some commands; however, the following manual pages serve as an excellent reference.
kill - Send signal to a process.
kill(1) kill(1) NAME kill - send a signal to a process; terminate a process SYNOPSIS kill [-s signame] pid ... kill [-s signum] pid ... kill -l Obsolescent Versions: kill -signame pid ... kill -signum pid ... DESCRIPTION The kill command sends a signal to each process specified by a pid process identifier. The default signal is SIGTERM, which normally terminates processes that do not trap or ignore the signal. pid is a process identifier, an unsigned or negative integer that can be one of the following: > 0 The number of a process. = 0 All processes, except special system processes, whose process group ID is equal to the process group ID of the sender. =-1 All processes, except special system processes, if the user has appropriate privileges. Otherwise, all processes, except special system processes, whose real or effective user ID is the same as the user ID of the sending process. <-1 All processes, except special system processes, whose process group ID is equal to the absolute value of pid and whose real or effective user ID is the same as the user of the sending process. Process numbers can be found with the ps command (see ps(1)) and with the built-in jobs command available in some shells. Options kill recognizes the following options: -l (ell) List all values of signame supported by the implementation. No signals are sent with this option. The symbolic names of the signals (without the SIG prefix) are written to standard output, separated by spaces and newlines. -s signame Send the specified signal name. The default is SIGTERM, number 15. signame can be specified in upper- and/or lowercase, with or without the SIG prefix. These values can be obtained by using the -l option. The symbolic name SIGNULL represents signal value zero. See "Signal Names and Numbers" below. -s signum Send the specified decimal signal number. The default is 15, SIGTERM. See "Signal Names and Numbers" below. -signame (Obsolescent.) Equivalent to -s signame. -signum (Obsolescent.) Equivalent to -s signum. Signal Names and Numbers The following table describes a few of the more common signals that can be useful from a terminal. For a complete list and a full description, see the header file <signal.h> and the manual entry signal(5). signum signame Name Description ___________________________________________________________________________ 0 SIGNULL Null Check access to pid 1 SIGHUP Hangup Terminate; can be trapped 2 SIGINT Interrupt Terminate; can be trapped 3 SIGQUIT Quit Terminate with core dump; can be trapped 9 SIGKILL Kill Forced termination; cannot be trapped 15 SIGTERM Terminate Terminate; can be trapped 24 SIGSTOP Stop Pause the process; cannot be trapped 25 SIGTSTP Termina stop Pause the process; can be trapped 26 SIGCONT Continue Run a stopped process SIGNULL (0), the null signal, invokes error checking but no signal is actually sent. This can be used to test the validity or existence of pid. SIGTERM (15), the (default) terminate signal, can be trapped by the receiving process, allowing the receiver to execute an orderly shutdown or to ignore the signal entirely. For orderly operations, this is the perferred choice. SIGKILL (9), the kill signal, forces a process to terminate immediately. Since SIGKILL cannot be trapped or ignored, it is useful for terminating a process that does not respond to SIGTERM. The receiving process must belong to the user of the sending process, unless the user has appropriate privileges. As a single special case, the continue signal SIGCONT can be sent to any process that is a member of the same session as the sending process. RETURN VALUE Upon completion, kill returns with one of the following values: 0 At least one matching process was found for each pid operand, and the specified signal was successfully processed for at least one matching process. >0 An error occurred. EXAMPLES The command: kill 6135 signals process number 6135 to terminate. This gives the process an opportunity to exit gracefully (removing temporary files, etc.). The following equivalent commands: kill -s SIGKILL 6135 kill -s KILL 6135 kill -s 9 6135 kill -SIGKILL 6135 kill -KILL 6135 kill -9 6135 terminate process number 6135 abruptly by sending a SIGKILL signal to the process. This tells the kernel to remove the process immediately. WARNINGS If a process hangs during some operation (such as I/O) so that it is never scheduled, it cannot die until it is allowed to run. Thus, such a process may never go away after the kill. Similarly, defunct processes (see ps(1)) may have already finished executing, but remain on the system until their parent reaps them (see wait(2)). Using kill to send signals to them has no effect. Some non-HP-UX implementations provide kill only as a shell built-in command. DEPENDENCIES This manual entry describes the external command /usr/bin/kill and the built-in kill command of the POSIX shell (see sh-posix(1)). Other shells, such as C and Korn (see csh(1) and ksh(1) respectively), also provide kill as a built-in command. The syntax for and output from these built-ins may be different. SEE ALSO csh(1), ksh(1), ps(1), sh(1), sh-bourne(1), sh-posix(1), kill(2), wait(2), signal(5). STANDARDS CONFORMANCE kill: SVID2, SVID3, XPG2, XPG3, XPG4, POSIX.2
ksh - Command programming language.
ksh(1) ksh(1) NAME ksh, rksh - shell, the standard/restricted command programming language SYNOPSIS ksh [+aefhikmnoprstuvx] [+o option] ... [-c string] [arg ...] rksh [+aefhikmnoprstuvx] [+o option] ... [-c string] [arg ...] DESCRIPTION ksh is a command programming language that executes commands read from a terminal or a file. rksh is a restricted version of the command interpreter ksh, used to set up login names and execution environments whose capabilities are more controlled than those of the standard shell. See Invoking ksh and Special Commands sections later in this entry for details about command line options and arguments, particularly the set command. Definitions metacharacter One of the following characters: ;&()|<> new-line space tab blank A tab or space character. identifier A sequence of letters, digits, or underscores starting with a letter or underscore. Identifiers are used as names for functions and named parameters. word A sequence of characters separated by one or more non- quoted metacharacters . command A sequence of characters in the syntax of the shell language. The shell reads each command and carries out the desired action, either directly or by invoking separate utilities. special command A command that is carried out by the shell without creating a separate process. Often called ``built-in commands''. Except for documented side effects, most special commands can be implemented as separate utilities. # The # character is interpreted as the beginning of a comment. See Quoting below. Commands A simple-command is a sequence of blank-separated words that can be preceded by a parameter assignment list. (See Environment below). The first word specifies the name of the command to be executed. Except as specified below, the remaining words are passed as arguments to the invoked command. The command name is passed as argument 0 (see exec(2)). The value of a simple-command is its exit status if it terminates normally, or (octal) 200+status if it terminates abnormally (see signal(5) for a list of status values). A pipeline is a sequence of one or more commands separated by |. The standard output of each command except the last is connected by a pipe (see pipe(2)) to the standard input of the next command. Each command is run as a separate process; the shell waits for the last command to terminate. The exit status of a pipeline is the exit status of the last command in the pipeline. A list is a sequence of one or more pipelines separated by ;, &, &&, or ||, and optionally terminated by ;, &, or |&. Of these five symbols, ;, &, and |& have equal precedence. && and || have a higher but also equal precedence. A semicolon (;) causes sequential execution of the preceding pipeline; an ampersand (&) causes asynchronous execution of the preceding pipeline (that is, the shell does not wait for that pipeline to finish). The symbol |& causes asynchronous execution of the preceding command or pipeline with a two-way pipe established to the parent shell (known as a co-process). The standard input and output of the spawned command can be written to and read from by the parent shell using the -p option of the special commands read and print described later. The symbol && (||) causes the list following it to be executed only if the preceding pipeline returns a zero (non-zero) value. An arbitrary number of new-lines can appear in a list, instead of semicolons, to delimit commands. A command is either a simple-command or one of the following. Unless otherwise stated, the value returned by a command is that of the last simple-command executed in the command. for identifier [in word ...] do list done Each time for is executed, identifier is set to the next word taken from the in word list. If in word ... is omitted, for executes the do list once for each positional parameter set (see Parameter Substitution below). Execution ends when there are no more words in the list. select identifier [in word...] do list done A select command prints on standard error (file descriptor 2), the set of words, each preceded by a number. If in word ... is omitted, the positional parameters are used instead (see Parameter Substitution below). The PS3 prompt is printed and a line is read from the standard input. If this line consists of the number of one of the listed words, the value of the parameter identifier is set to the word corresponding to this number. If this line is empty, the selection list is printed again. Otherwise the value of the parameter identifier is set to null. The contents of the line read from standard input is saved in the parameter REPLY. The list is executed for each selection until a break or end-of-file (eof) is encountered. case word in [[(] pattern [ |pattern] ... ) list ;;] ... esac A case command executes the list associated with the first pattern that matches word. The form of the patterns is identical to that used for file name generation (see File Name Generation below). if list then list [elif list then list] ... [else list]fi The list following if is executed and, if it returns a zero exit status, the list following the first then is executed. Otherwise, the list following elif is executed and, if its value is zero, the list following the next then is executed. Failing that, the else list is executed. If no else list or then list is executed, if returns a zero exit status. while list do list done until list do list done A while command repeatedly executes the while list, and if the exit status of the last command in the list is zero, executes the do list; otherwise the loop terminates. If no commands in the do list are executed, while returns a zero exit status; until can be used in place of while to negate the loop termination test. (list) Execute list in a separate environment. If two adjacent open parentheses are needed for nesting, a space must be inserted to avoid arithmetic evaluation as described below. { list;} Execute list, but not in a separate environment. Note that { is a keyword and requires a trailing blank to be recognized. [[ expression ]] Evaluates expression and returns a zero exit status when expression is true. See Conditional Expressions below, for a description of expression. Note that [[ and ]] are keywords and require blanks between them and expression. function identifier {list;} identifier () {list;} Define a function referred to by identifier. The body of the function is the list of commands between { and } (see Functions below). time pipeline pipeline is executed and the elapsed time, user time, and system time are printed on standard error. The following keywords are recognized only as the first word of a command and when not quoted: if then else elif fi case esac for while until do done { } function select time [[ ]] Comments A word beginning with # causes that word and all subsequent characters up to a new-line to be ignored. Aliasing The first word of each command is replaced by the text of an alias, if an alias for this word has been defined. An alias name consists of any number of characters excluding metacharacters, quoting characters, file expansion characters, parameter and command substitution characters, and =. The replacement string can contain any valid shell script, including the metacharacters listed above. The first word of each command in the replaced text, other than any that are in the process of being replaced, is tested for additional aliases. If the last character of the alias value is a blank, the word following the alias is also checked for alias substitution. Aliases can be used to redefine special built-in commands, but cannot be used to redefine the keywords listed above. Aliases can be created, listed, and exported with the alias command and can be removed with the unalias command. Exported aliases remain in effect for subshells but must be reinitialized for separate invocations of the shell (see Invoking ksh below). Aliasing is performed when scripts are read, not while they are executed. Therefore, for it to take effect, alias must be executed before the command referring to the alias is read. Aliases are frequently used as a shorthand for full path names. An option to the aliasing facility allows the value of the alias to be automatically set to the full path name of the corresponding command. These aliases are called tracked aliases. The value of a tracked alias is defined the first time the identifier is read and becomes undefined each time the PATH variable is reset. These aliases remain tracked so that the next reference redefines the value. Several tracked aliases are compiled into the shell. The -h option of the set command converts each command name that is an identifier into a tracked alias. The following exported aliases are compiled into the shell but can be unset or redefined: autoload='typeset -fu' false='let 0' functions='typeset -f' hash='alias -t -' history='fc -l' integer='typeset -i' nohup='nohup ' r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' true=':' type='whence -v' Tilde Substitution After alias substitution is performed, each word is checked to see if it begins with an unquoted ~. If it does, the word up to a /is checked to see if it matches a user name in the /etc/passwd file. If a match is found, the ~ and the matched login name are replaced by the login directory of the matched user. This is called a tilde substitution. If no match is found, the original text is left unchanged. A ~, alone or before a /, is replaced by the value of the HOME parameter. A ~ followed by a + or - is replaced by the value of the parameter PWD and OLDPWD, respectively. In addition, tilde substitution is attempted when the value of a parameter assignment begins with a ~. Command Substitution The standard output from a command enclosed in parenthesis preceded by a dollar sign ($(command)) or a pair of back single quotes (accent grave) (`command`) can be used as part or all of a word; trailing new-lines are removed. In the second (archaic) form, the string between the quotes is processed for special quoting characters before the command is executed (see Quoting below). The command substitution $(cat file) can be replaced by the equivalent but faster $(<file). Command substitution of most special commands (built-ins) that do not perform I/O redirection are carried out without creating a separate process. However, command substitution of a function creates a separate process to execute the function and all commands (built-in or otherwise) in that function. An arithmetic expression enclosed in double parenthesis preceded by a dollar sign ($((expression))) is replaced by the value of the arithmetic expression within the double parenthesis (see Arithmetic Evaluation below for a description of arithmetic expressions). Parameter Substitution A parameter is an identifier, one or more digits, or any of the characters *, @, #, ?, -, $, and !. A named parameter (a parameter denoted by an identifier) has a value and zero or more attributes. Named parameters can be assigned values and attributes by using the typeset special command. Attributes supported by ksh are described later with the typeset special command. Exported parameters pass values and attributes to the environment. The shell supports a limited one-dimensional array facility. An element of an array parameter is referenced by a subscript. A subscript is denoted by a [ followed by an arithmetic expression (see Arithmetic Evaluation below) followed by a ]. To assign values to an array, use set -A name value .... The value of all subscripts must be in the range of 0 through 1023. Arrays need not be declared. Any reference to a named parameter with a valid subscript is legal and an array is created if necessary. Referencing an array without a subscript is equivalent to referencing the first element. The value of a named parameter can also be assigned by writing: name=value [name=value] ... If the -i integer attribute is set for name, the value is subject to arithmetic evaluation as described below. Positional parameters, parameters denoted by a number, can be assigned values with the set special command. Parameter $0 is set from argument zero when the shell is invoked. The character $ is used to introduce substitutable parameters. ${parameter} Substitute the value of the parameter, if any. Braces are required when parameter is followed by a letter, digit, or underscore that should not be interpreted as part of its name or when a named parameter is subscripted. If parameter is one or more digits, it is a positional parameter. A positional parameter of more than one digit must be enclosed in braces. If parameter is * or @ all the positional parameters, starting with $1, are substituted (separated by a field separator character). If an array identifier with subscript * or @ is used, the value for each element is substituted (separated by a field separator character). The shell reads all the characters from ${ to the matching } as part of the same word even if it contains braces or metacharacters. ${#parameter} If parameter is * or @, the number of positional parameters is substituted. Otherwise, the length of the value of the parameter is substituted. ${#identifier[*]} Substitute the number of elements in the array identifier. ${parameter:-word} If parameter is set and is non-null, substitute its value; otherwise substitute word. ${parameter:=word} If parameter is not set or is null, set it to word; then substitute the value of the parameter. Positional parameters cannot be assigned in this way. ${parameter:?word} If parameter is set and is non-null, substitute its value; otherwise, print word and exit from the shell. If word is omitted, a standard message is printed. ${parameter:+word} If parameter is set and is non-null, substitute word; otherwise substitute nothing. ${parameter#pattern} ${parameter##pattern} If the shell pattern matches the beginning of the value of parameter, the value of this substitution is the value of the parameter with the matched portion deleted otherwise the value of this parameter is substituted. In the former case, the smallest matching pattern is deleted; in the latter case, the largest matching pattern is deleted. ${parameter%pattern} ${parameter%%pattern} If the shell pattern matches the end of the value of parameter, the value of parameter with the matched part is deleted; otherwise substitute the value of parameter. In the former, the smallest matching pattern is deleted; in the latter, the largest matching pattern is deleted. In the above, word is not evaluated unless it is used as the substituted string. Thus, in the following example, pwd is executed only if d is not set or is null: echo ${d:-$(pwd)} If the colon (:) is omitted from the above expressions, the shell only checks to determine whether or not parameter is set. The following parameters are set automatically by the shell: # The number of positional parameters in decimal. - Options supplied to the shell on invocation or by the set command. ? The decimal value returned by the last executed command. $ The process number of this shell. _ Initially, the value of _ is an absolute pathname of the shell or script being executed as passed in the environment. Subsequently it is assigned the last argument of the previous command. This parameter is not set for commands which are asynchronous. This parameter is also used to hold the name of the matching MAIL file when checking for mail. ! The process number of the last background command invoked. COLUMNS If this variable is set, its value is used to define the width of the edit window for the shell edit modes and for printing select lists. In a windowed environment, if the shell detects that the window size has changed, the shell updates the value of COLUMNS. ERRNO The value of errno as set by the most recently failed system call. This value is system dependent and is intended for debugging purposes. LINENO The line number of the current line within the script or function being executed. LINES If this variable is set, the value is used to determine the column length for printing select lists. select lists print vertically until about two-thirds of LINES lines are filled. In a windowed environment, if the shell detects that the window size has changed, the shell updates the value of LINES. OLDPWD The previous working directory set by the cd command. OPTARG The value of the last option argument processed by the getopts special command. OPTIND The index of the last option argument processed by the getopts special command. PPID The process number of the parent of the shell. PWD The present working directory set by the cd command. RANDOM Each time this parameter is evaluated, a random integer, uniformly distributed between 0 and 32767, is generated. The sequence of random numbers can be initialized by assigning a numeric value to RANDOM. REPLY This parameter is set by the select statement and by the read special command when no arguments are supplied. SECOND Each time this parameter is referenced, the number of seconds since shell invocation is returned. If this parameter is assigned a value, the value returned upon reference is the value that was assigned plus the number of seconds since the assignment. The following parameters are used by the shell: CDPATH The search path for the cd command. EDITOR If the value of this variable ends in emacs, gmacs, or vi and the VISUAL variable is not set, the corresponding option is turned on (see set in Special Commands below). ENV If this parameter is set, parameter substitution is performed on the value to generate the path name of the script to be executed when the shell is invoked (see Invoking ksh below). This file is typically used for alias and function definitions. FCEDIT The default editor name for the fc command. FPATH The search path for function definitions. This path is searched when a function with the -u attribute is referenced and when a command is not found. If an executable file is found, then it is read and executed in the current environment. IFS Internal field separators, normally space, tab, and new-line that are used to separate command words resulting from command or parameter substitution, and for separating words with the special command read. The first character of the IF parameter is used to separate arguments for the "$*" substitution (see Quoting below). HISTFIL If this parameter is set when the shell is invoked, its value is the path name of the file that is used to store the command history. The default value is $HOME/.sh_history. If the user has appropriate privileges and no HISTFILE is given, then no history file is used (see Command Re-entry below). HISTSIZE If this parameter is set when the shell is invoked, the number of previously entered commands accessible to this shell will be greater than or equal to this number. The default is 128. HOME The default argument (home directory) for the cd command. MAIL If this parameter is set to the name of a mail file and the MAILPATH parameter is not set, the shell informs the user of arrival of mail in the specified file. MAILCHECK This variable specifies how often (in seconds) the shell checks for changes in the modification time of any of the files specified by the MAILPATH or MAIL parameters. The default value is 600 seconds. When the time has elapsed the shell checks before issuing the next prompt. MAILPATH A list of file names separated by colons (:). If this parameter is set, the shell informs the user of any modifications to the specified files that have occurred within the last MAILCHECK seconds. Each file name can be followed by a ? and a message to be printed, in which case the message undergoes parameter and command substitution with the parameter $_ defined as the name of the changed file. The default message is you have mail in $_. PATH The search path for commands (see Execution below). The user cannot change PATH if executing rksh (except in the .profile file). PS1 The value of this parameter is expanded for parameter substitution, to define the primary prompt string which, by default, is $ followed by a space character. The character ! in the primary prompt string is replaced by the command number (see Command Re-entry below). To include a !in the prompt, use !!. PS2 Secondary prompt string, by default > followed by a space character. PS3 election prompt string used within a select loop, by default #? followed by a space character. PS4 The value of this variable is expanded for parameter substitution and precedes each line of an execution trace. If PS4 is unset, the execution trace prompt is + followed by a space character. SHELL The path name of the shell is kept in the environment. When invoked, the shell is restricted if the value of this variable contains an r in the basename. TMOUT If set to a value greater than zero, the shell terminates if a command is not entered within the prescribed number of seconds after issuing the PS1 prompt. VISUAL Invokes the corresponding option when the value of this variable ends in emacs, gmacs, or vi (see set in Special Commands below). The shell gives default values to PATH, PS1, PS2, MAILCHECK, TMOUT, and IFS. HOME, SHELL, ENV, and MAIL are never set automatically by the shell (although HOME, SHELL, and MAIL are set by login(1)). Blank Interpretation After parameter and command substitution, the results of substitution are scanned for field separator characters (found in IFS), and split into distinct arguments where such characters are found. ksh retains explicit null arguments ( or '') but removes implicit null arguments (those resulting from parameters that have no values). File Name Generation Following substitution, each command word is processed as a pattern for file name expansion unless the -f option has been set. The form of the patterns is the Pattern Matching Notation defined by regexp(5). The word is replaced with sorted file names matching the pattern. If no file name is found that matches the pattern, the word is left unchanged. In addition to the notation described in regexp(5), ksh recognizes composite patterns made up of one or more pattern lists separated from each other with a |. Composite patterns can be formed with one or more of the following: ?(pattern-list) Optionally matches any one of the given patterns. *(pattern-list) Matches zero or more occurrences of the given patterns. +(pattern-list) Matches one or more occurrences of the given patterns. @(pattern-list) Matches exactly one of the given patterns. !(pattern-list) Matches anything, except one of the given patterns. Quoting Each of the metacharacters listed above (See Definitions above) has a special meaning to the shell and causes termination of a word unless quoted. A character can be quoted (i.e., made to stand for itself) by preceding it with a \. The pair \new-line is ignored. All characters enclosed between a pair of single quote marks (''), are quoted. A single quote cannot appear within single quotes. Inside double quote marks (""), parameter and command substitution occurs and \ quotes the characters \, `, ", and $. $* and $@ have identical meanings when not quoted or when used as a parameter assignment value or as a file name. However, when used as a command argument, "$*" is equivalent to "$1d$2d...", where d is the first character of the IFS parameter, whereas "$@" is equivalent to "$1" "$2" .... Inside back single quote (accent grave) marks (``) \ quotes the characters \, `, and $. If the back single quotes occur within double quotes, \ also quotes the character ". The special meaning of keywords or aliases can be removed by quoting any character of the keyword. The recognition of function names or special command names listed below cannot be altered by quoting them. Arithmetic Evaluation The ability to perform integer arithmetic is provided with the special command let. Evaluations are performed using long arithmetic. Constants take the form [base#]n, where base is a decimal number between two and thirty-six representing the arithmetic base and n is a number in that base. If base is omitted, base 10 is used. An arithmetic expression uses the same syntax, precedence, and associativity of expression of the C language. All the integral operators, other than ++, --, ?:, and , are supported. Variables can be referenced by name within an arithmetic expression without using the parameter substitution syntax. When a variable is referenced, its value is evaluated as an arithmetic expression. An internal integer representation of a variable can be specified with the -i option of the typeset special command. Arithmetic evaluation is performed on the value of each assignment to a variable with the -i attribute. If you do not specify an arithmetic base, the first assignment to the variable determines the arithmetic base. This base is used when parameter substitution occurs. Since many of the arithmetic operators require quoting, an alternative form of the let command is provided. For any command beginning with ((, all characters until the matching )) are treated as a quoted expression. More precisely, ((...)) is equivalent to let "...". Prompting When used interactively, the shell prompts with the value of PS1 before reading a command. If at any time a new-line is typed and further input is needed to complete a command, the secondary prompt (the value of PS2) is issued. Conditional Expressions. A conditional expression is used with the [[ compound command to test attributes of files and to compare strings. Word splitting and file name generation are not performed on the words between [[ and ]]. Each expression can be constructed from one or more of the following unary or binary expressions: -a file True if file exists. -b file True if file exists and is a block special file. -c file True if file exists and is a character special file. -d file True if file exists and is a directory. -f file True if file exists and is an ordinary file. -g file True if file exists and is has its setgid bit set. -h file True if file exists and is a a symbolic link. -k file True if file exists and is has its sticky bit set. -n string True if length of string is non-zero. -o option True if option named option is on. -p file True if file exists and is a fifo special file or a pipe. -r file True if file exists and is readable by current process. -s file True if file exists and has size greater than zero. -t fildes True if file descriptor number fildes is open and associated with a terminal device. -u file True if file exists and is has its setuid bit set. -w file True if file exists and is writable by current process. -x file True if file exists and is executable by current process. If file exists and is a directory, the current process has permission to search in the directory. -z string True if length of string is zero. -H file True if file exists and is a hidden directory (see cdf(4)). -L file True if file exists and is a symbolic link. -O file True if file exists and is owned by the effective user ID of this process. -G file True if file exists and its group matches the effective group ID of this process. -S file True if file exists and is a socket. file1 -nt file2 True if file1 exists and is newer than file2. file1 -ot file2 True if file1 exists and is older than file2. file1 -ef file2 True if file1 and file2 exist and refer to the same file. string = pattern True if string matches pattern. string != pattern True if string does not match pattern. string1 < string2 True if string1 comes before string2 based on ASCII value of their characters. string1 > string2 True if string1 comes after string2 based on ASCII value of their characters. exp1 -eq exp2 True if exp1 is equal to exp2. exp1 -ne exp2 True if exp1 is not equal to exp2. exp1 -lt exp2 True if exp1 is less than exp2. exp1 -gt exp2 True if exp1 is greater than exp2. exp1 -le exp2 True if exp1 is less than or equal to exp2. exp1 -ge exp2 True if exp1 is greater than or equal to exp2. A compound expression can be constructed from these primitives by using any of the following, listed in decreasing order of precedence. (expression) True, if expression is true. Used to group expressions. ! expression True if expression is false. expression1 && expression2 True, if expression1 and expression2 are both true. expression1 || expression2 True, if either expression1 or expression2 is true. Input/Output Before a command is executed, its input and output can be redirected using a special notation interpreted by the shell. The following can appear anywhere in a simple-command or can precede or follow a command and are not passed on to the invoked command. Command and parameter substitution occurs before word or digit is used, except as noted below. File name generation occurs only if the pattern matches a single file and blank interpretation is not performed. <word se file word as standard input (file descriptor 0). >word Use file word as standard output (file descriptor 1). If the file does not exist, it is created. If the file exists, and the noclobber option is on, an error occurs; otherwise, the file is truncated to zero length. >|word Sames as >, except that it overrides the noclobber option. >>word Use file word as standard output. If the file exists, output is appended to it (by first searching for the end-of-file); otherwise, the file is created. <>word Open file word for reading and writing as standard input. If the file does not exist it is created. <<[-]word The shell input is read up to a line that matches word, or to an end-of-file. No parameter substitution, command substitution, or file name generation is performed on word. The resulting document, called a here-document, becomes the standard input. If any character of word is quoted, no interpretation is placed upon the characters of the document. Otherwise, parameter and command substitution occurs, \new-line is ignored, and \ must be used to quote the characters \, $, `, and the first character of word. If - is appended to <<, all leading tabs are stripped from word and from the document. <&digit The standard input is duplicated from file descriptor digit (see dup(2)). >&digit The standard output is duplicated to file descriptor digit (see dup(2)). <&- The standard input is closed. >&- The standard output is closed. <&p The input from the co-process is moved to standard input. >&p The output to the co-process is moved to standard output. If one of the above is preceded by a digit, the file descriptor number cited is that specified by the digit (instead of the default 0 or 1). For example: ... 2>&1 means file descriptor 2 is to be opened for writing as a duplicate of file descriptor 1. Redirection order is significant because the shell evaluates redirections referencing file descriptors in terms of the currently open file associated with the specified file descriptor at the time of evaluation. For example: ... 1>fname 2>&1 first assigns file descriptor 1 (standard output) to file fname, then assigns file descriptor 2 (standard error) to the file assigned to file descriptor 1; i.e., fname. On the other hand, if the order of redirection is reversed as follows: ... 2>&1 1>fname file descriptor 2 is assigned to the current standard output (user terminal unless a different assignment is inherited). File descriptor 1 is then reassigned to file fname without changing the assignment of file descriptor 2. The input and output of a co-process can be moved to a numbered file descriptor allowing other commands to write to them and read from them using the above redirection operators. If the input of the current co-process is moved to a numbered file descriptor, another co-process can be started. If a command is followed by & and job control is inactive, the default standard input for the command is the empty file /dev/null. Otherwise, the environment for the execution of a command contains the file descriptors of the invoking shell as modified by input/output specifications. Environment The environment (see environ(5)) is a list of name-value pairs passed to an executed program much like a normal argument list. The names must be identifiers and the values are character strings. The shell interacts with the environment in several ways. When invoked, the shell scans the environment and creates a parameter for each name found, gives it the corresponding value, and marks it export. Executed commands inherit the environment. If the user modifies the values of these parameters or creates new ones by using the export or typeset -x commands, the values become part of the environment. The environment seen by any executed command is thus composed of any name-value pairs originally inherited by the shell whose values can be modified by the current shell, plus any additions which must be noted in export or typeset -x commands. The environment for any simple-command or function can be augmented by prefixing it with one or more parameter assignments. A parameter assignment argument takes the form identifier=value. For example, TERM=450 cmd args and (export TERM; TERM=450; cmd args) are equivalent (as far as the above execution of cmd is concerned except for special commands listed below that are preceded by a dagger). If the -k option is set, all parameter assignment arguments are placed in the environment, even if they occur after the command name. The following echo statement prints a=b c. After the -k option is set, the second echo statement prints only c: echo a=b c set -k echo a=b c This feature is intended for use with scripts written for early versions of the shell, and its use in new scripts is strongly discouraged. It is likely to disappear someday. Functions The function keyword (described in the Commands section above) is used to define shell functions. Shell functions are read and stored internally. Alias names are resolved when the function is read. Functions are executed like commands, with the arguments passed as positional parameters (see Execution below). Functions execute in the same process as the caller except that command substitution of a function creates a new process. Functions share all files and present working directory with the caller. Traps caught by the caller are reset to their default action inside the function. If a function does not catch or specifically ignore a trap condition, the function terminates and the condition is passed on to the caller. A trap on EXIT set inside a function is executed after the function completes in the environment of the caller. Ordinarily, variables are shared between the calling program and the function. However, the typeset special command used within a function defines local variables whose scope includes the current function and all functions it calls. The special command return is used to return from function calls. Errors within functions return control to the caller. Function identifiers can be listed with the +f option of the typeset special command. Function identifiers and the associated text of the functions can be listed with the -f option. Functions can be undefined with the -f option of the unset special command. Ordinarily, functions are unset when the shell executes a shell script. The -xf option of the typeset command allows a function to be exported to scripts that are executed without reinvoking the shell. Functions that must be defined across separate invocations of the shell should be placed in the ENV file. Jobs If the monitor option of the set command is turned on, an interactive shell associates a job with each pipeline. It keeps a table of current jobs, printed by the jobs command, and assigns them small integer numbers. When a job is started asynchronously with &, the shell prints a line resembling: [1] 1234 indicating that job number 1 was started asynchronously and had one (top-level) process whose process ID was 1234. If you are running a job and want to do something else, type the suspend character (usually ^Z (Ctrl-Z)) to send a STOP signal to the current job. The shell then indicates that the job has been `Stopped', and prints another prompt. The state of this job can be manipulated by using the bg command to put it in the background, running other commands (while it is stopped or running in the background), and eventually restarting or returning the job to the foreground by using the fg command. A ^Z takes effect immediately and resembles an interrupt, since pending output and unread input are discarded when ^Z is typed. A job run in the background stops if it tries to read from the terminal. Background jobs normally are allowed to produce output, but can be disabled by giving the stty tostop command. If the user sets this tty option, background jobs stop when trying to produce output. There are several ways to refer to jobs in the shell. A job can be referred to by the process ID of any process in the job or by one of the following: %number The job with the given number. %string Any job whose command line begins with string. %?string Any job whose command line contains string. %% Current job. %+ Equivalent to %%. %- Previous job. The shell learns immediately when a process changes state. It informs the user when a job is blocked and prevented from further progress, but only just before it prints a prompt. When the monitor mode is on, each background job that completes triggers any trap set for CHLD. Attempting to leave the shell while jobs are running or stopped produces the warning, You have stopped (running) jobs. Use the jobs command to identify them. An immediate attempt to exit again terminates the stopped jobs; the shell does not produce a warning the second time. Signals The INT and QUIT signals for an invoked command are ignored if the command is followed by & and the monitor option is off. Otherwise, signals have the values inherited by the shell from its parent, with the exception of signal 11 (but see also the trap command below). Execution Substitutions are made each time a command is executed. If the command name matches one of the Special Commands listed below, it is executed within the current shell process. Next, ksh checks the command name to determine whether it matches one of the user-defined functions. If it does, ksh saves the positional parameters and then sets them to the arguments of the function call. The positional parameter 0 is set to the function name. When the function completes or issues a return, ksh restores the positional parameter list and executes any trap set on EXIT within the function. The value of a function is the value of the last command executed. A function is executed in the current shell process. If a command name is not a special command or a user-defined function, ksh creates a process and attempts to execute the command using exec (see exec(2)). The shell parameter PATH defines the search path for the directory containing the command. Alternative directory names are separated by a colon (:). The default path is /usr/bin: (specifying /usr/bin and the current directory in that order). Note that the current directory is specified by a null path name which can appear immediately after the equals sign, between colon delimiters, or at the end of the path list. The search path is not used if the command name contains a /. Otherwise, each directory in the path is searched for an executable file. If the file has execute permissions but is not a directory or an executable object code file, it is assumed to be a script file, which is a file of data for an interpreter. If the first two characters of the script file are #!, exec (see exec(2)) expects an interpreter path name to follow. exec then attempts to execute the specified interpreter as a separate process to read the entire script file. If a call to exec fails, /usr/bin/ksh is spawned to interpret the script file. All non-exported aliases, functions, and named parameters are removed in this case. If the shell command file does not have read permission, or if the setuid and/or setgid bits are set on the file, the shell executes an agent to set up the permissions and execute the shell with the shell command file passed down as an open file. A parenthesized command is also executed in a sub-shell without removing non-exported quantities. Command Re-entry The text of the last HISTSIZE (default 128) commands entered from a terminal device is saved in a history file. The file $ HOME/.sh_history is used if the HISTFILE variable is not set or writable. A shell can access the commands of all interactive shells that use the same named HISTFILE. The special command fc is used to list or edit a portion of this file. The portion of the file to be edited or listed can be selected by number or by giving the first character or characters of the command. A single command or range of commands can be specified. If no editor program is specified as an argument to fc, the value of the FCEDIT parameter is used. If FCEDIT is not defined, /usr/bin/ed is used. The edited command is printed and re-executed upon leaving the editor. The editor name - is used to skip the editing phase and to re-execute the command. In this case a substitution parameter of the form old=new can be used to modify the command before execution. For example, if r is aliased to fc -e -, typing r bad=good c re-executes the most recent command that starts with the letter c and replaces the first occurrence of the string bad with the string good.
umask - Display or set creation mask.
umask(1) umask(1) NAME umask - set or display the file mode creation mask SYNOPSIS Set Mask: umask mask Display Mask: umask [-S] DESCRIPTION The umask command sets the value of the file mode creation mask or displays the current one. The mask affects the initial value of the file mode (permission) bits for subsequently created files. Setting the File Mode Creation Mask The umask mask command sets a new file mode creation mask for the current shell execution environment. mask can be a symbolic or numeric (obsolescent) value. A symbolic mask provides a flexible way of modifying the mask permission bits individually or as a group. A numeric mask specifies all the permission bits at one time. When a mask is specified, no output is written to standard output. Symbolic Mask Value A symbolic mask replaces or modifies the current file mode creation mask. It is specified as specified as a comma-separated list of operations in the following format. Whitespace is not permitted. [who][operator][permissions][,...] The fields can have the following values: who One or more of the following letters: u Modify permissions for user (owner). g Modify permissions for group. o Modify permissions for others. Or: a Modify permissions for all (a = ugo). operator One of the following symbols: + Add permissions to the existing mask for who. - Delete permissions from the existing mask for who. = Replace the existing mask for who with permissions. permissions One or more of the following letters: r The read permission. w The write permission. x The execute/search permission. If one or two of the fields are omitted, the following table applies: Format Entered Effect | Input Equals _________________________________________________________ |_______________ who Delete current permissions for who | g g= operator No action | - (none) permissions Equal to: a+permissions | rw a+rw who= Delete current permissions for who | u= u= who+ No action | u+ (none) who- No action | u- (none) whopermissions Equal to: who=permissions | ux u=x operatorpermissions Equal to: aoperatorpermissions | -rw a-rw Numeric Mask Value (Obsolescent) A numeric mask replaces the current file mode creation mask. It is specified as an unsigned octal integer, constructed from the logical OR (sum) of the following mode bits (leading zeros can be omitted): 0400 ( a=rwx,u-r) Read by owner 0200 ( a=rwx,u-w) Write by owner 0100 ( a=rwx,u-x) Execute (search in directory) by owner 0040 ( a=rwx,g-r) Read by group 0020 ( a=rwx,g-w) Write by group 0010 ( a=rwx,g-x) Execute/search by group 0004 ( a=rwx,o-r) Read by others 0002 ( a=rwx,o-w) Write by others 0001 ( a=rwx,o-x) Execute/search by others Displaying the Current Mask Value To display the current file mode creation mask value, use one of the commands: umask -S Print the current file mode creation mask in a symbolic format: u=[r][w][x],g=[r][w][x],o=[r][w][x] The characters r (read), w (write), and x (execute/search) represent the bits that are clear in the mask for u (user/owner), g (group), and o (other). All other bits are set. umask Print the current file mode creation mask as an octal value. The zero bits in the numeric value correspond to the displayed r, w, and x permission characters in the symbolic value. The one bits in the numeric value correspond to the missing permission characters in the symbolic value. Depending on implementation, the display consists of one to four octal digits; the first digit is always zero (see DEPENDENCIES). The rightmost three digits (leading zeros implied as needed) represent the bits that are set or clear in the mask. Both forms produce output that can be used as the mask argument to set the mask in a subsequent umask command. General Operation When a new file is created (see creat(2)), each bit that is set in the file mode creation mask causes the corresponding permission bit in the the file mode to be cleared (disabled). Conversely, bits that are clear in the mask allow the corresponding file mode bits to be enabled in newly created files. For example, the mask u=rwx,g=rx,o=rx (022) disables group and other write permissions. As a result, files normally created with a file mode shown by the ls -l command as -rwxrwxrwx (777) become mode - rwxr-xr-x (755); while files created with file mode -rw-rw-rw- (666) become mode -rw-r--r-- (644). Note that the file creation mode mask does not affect the set-user-id, set-group-id, or "sticky" bits. The file creation mode mask is also used by the chmod command (see chmod(1)). Since umask affects the current shell execution environment, it is generally provided as a shell regular built-in (see DEPENDENCIES. If umask is called in a subshell or separate utility execution environment, such as one of the following: (umask 002) nohup umask ... find . -exec umask ... it does not affect the file mode creation mask of the calling environment. The default mask is u=rwx,g=rwx,o=rwx (000). RETURN VALUE umask exits with one of the following values: 0 The file mode creation mask was successfully changed or no mask operand was supplied. >0 An error occurred. EXAMPLES In these examples, each line show an alternate way of accomplishing the same task. Set the umask value to produce read and write permissions for the file's owner and read permissions for all others (ls -l displays - rw-r--r-- on newly created files): umask u=rwx,g=rx,o=rx symbolic mode umask a=rx,u+w symbolic mode umask 022 numeric mode Set the umask value to produce read, and write permissions for the file's owner, read-only for others users in the same group, and no access to others (-rw-r-----): umask a-rwx,u+rw,g+r symbolic mode umask 137 numeric mode Set the umask value to deny read, write, and execute permissions to everyone (----------): umask a= symbolic mode umask 777 numeric mode Add the write permission to the current mask for everyone (there is no equivalent numeric mode): umask a+w symbolic mode WARNINGS If you set a mask that prevents read or write access for the user (owner), many programs, such as editors, that create temporary files will fail because they cannot access the file data. DEPENDENCIES The umask command is implemented both as a separate executable file (/usr/bin/umask) and as built-in shell commands. POSIX Shell and Separate File All features are supported (see sh-posix(1). The numeric mask display uses a minimum of two digits. Korn Shell The -S option is not supported in the Korn shell built-in command (see ksh(1). The numeric mask display uses a minimum of two digits. C Shell The -S option and symbolic mask values are not supported in the C shell built-in command (see csh(1). The numeric mask display uses a minimum of one digit. Bourne Shell The -S option and symbolic mask values are not supported in the Bourne shell built-in command (see sh-bourne(1). The numeric mask display always consists of four digits. SEE ALSO chmod(1), csh(1), ksh(1), sh-posix(1), sh(1), chmod(2), creat(2), umask(2). STANDARDS CONFORMANCE umask: SVID2, SVID3, XPG2, XPG3, XPG4, POSIX.2
CONTENTS |