Most UNIX variants allow you to select among several shells. Because of its versatility and ease of use, many system administrators configure the KornShell for new users. The KornShell was derived from the Bourne Shell and has much of the same functionality of the Bourne Shell. ksh is the program you run on most UNIX systems, including HP-UX, that supplies KornShell functionality. It is also often referred to as the K shell. I use ksh throughout this chapter. You can use the ksh in the following three ways:
Interactively type commands on the command line.
Group commonly executed sets of commands into command files that you can execute by typing the name of the file.
Create KornShell programs using the structured programming techniques of the shell.
These three techniques are listed in the order in which you'll probably use them. First, you log in and use interactive commands. Then you group together commonly used commands and execute them with a single command. Finally, you may want to create sophisticated shell scripts.
For this reason, I describe these aspects of the KornShell in the order in which they are listed. The command file and programming aspects of the KornShell are covered as part of the Shell Programming Chapter 28.
The examples in this chapter are performed on a variety of different systems, not just HP-UX. This is because many system administrators use ksh on several different UNIX variants. You would probably find both your user setup and the operation of the KornShell on other systems similar to the description in this chapter. Much of the setup of any shell is performed by the system administrator, so you will surely find differences in your KornShell setup compared with what is shown in this chapter. In general, however, the operation of the KornShell is similar from one system to another.
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 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 means that we really started at command number five when we requested to start the list from command number zero.
To produce a list from command 100 to the present command, we issue the following:
martyp $ history 100
100 ls
101 alias
102 unalias ls
103 ls
104 ls -al
105 alias
106 history
107 alias
108 unalias history
109 history
110 fc -l
111 history
112 alias hisotry="fc -l"
113 history
114 alias history="fc -l"
115 history
116 history 128
117 history 128 | more
118 history 200
119 alias
120 history 1
121 inv
122 env
123 env | more
124 history 1
125 more .profile
126 env | grep HIS
127 exit
128 env
129 env | grep HIS
130 more .profile
131 history
132 history 0
133 history
134 history -n
135 history 100
martyp $
To list the current command and the 20 commands preceding it, we issue the following:
martyp $ history -20 116 history 128 117 history 128 | more 118 history 200 119 alias 120 history 1 121 inv 122 env 123 env | more 124 history 1 125 more .profile 126 env | grep HIS 127 exit 128 env 129 env | grep HIS 130 more .profile 131 history 132 history 0 133 history 134 history -n 135 history 100 136 history -20 martyp $
The -20 goes back from the current command a full 20 commands. In this case, history is using the current command as the default place to begin producing the list. You can list the last 20 commands preceding the current command by specifying the range -1 -20 as shown in the following example:
martyp $ history -1 -20
136 history -20
135 history 100
134 history -n
133 history
132 history 0
131 history
130 more .profile
129 env | grep HIS
128 env
127 exit
126 env | grep HIS
125 more .profile
124 history 1
123 env | more
122 env
121 inv
120 history 1
119 alias
118 history 200
117 history 128 | more
martyp $
Notice in this example that the current command, history -1 -20, is not shown in the list because the -1 starts the list with the preceding command. This is effectively producing a range of commands to list.
You can also reverse the order of the last 20 commands by specifying --20 first and then the -1 as shown in the following example:
martyp $ history -20 -1 118 history 200 119 alias 120 history 1 121 inv 122 env 123 env | more 124 history 1 125 more .profile 126 env | grep HIS 127 exit 128 env 129 env | grep HIS 130 more .profile 131 history 132 history 0 133 history 134 history -n 135 history 100 136 history -20 137 history -1 -20 martyp $
You can also produce a list from the last time that a command was issued to the current command. The following example shows producing a list from the last fc command to the current command:
martyp $ history fc 110 fc -l 111 history 112 alias hisotry="fc -l" 113 history 114 alias history="fc -l" 115 history 116 history 128 117 history 128 | more 118 history 200 119 alias 120 history 1 121 inv 122 env 123 env | more 124 history 1 125 more .profile 126 env | grep HIS 127 exit 128 env 129 env | grep HIS 130 more .profile 131 history 132 history 0 133 history 134 history -n 135 history 100 136 history -20 137 history -1 -20 138 history -20 -1 139 history 140 history grep 141 history env 142 history 143 history fc martyp $
You can also reverse this list using the -r option as shown in the following example:
martyp $ history -r fc
144 history -r fc
143 history fc
142 history
141 history env
140 history grep
139 history
138 history -20 -1
137 history -1 -20
136 history -20
135 history 100
134 history -n
133 history
132 history 0
131 history
130 more .profile
129 env | grep HIS
128 env
127 exit
126 env | grep HIS
125 more .profile
124 history 1
123 env | more
122 env
121 inv
120 history 1
119 alias
118 history 200
117 history 128 | more
116 history 128
115 history
114 alias history="fc -l"
113 history
112 alias hisotry="fc -l"
111 history
110 fc -l
martyp $
Having access to this history list is a great feature of the KornShell. You can view all the commands you have issued, including your typing errors, in any format you wish. In the next section, we start using the commands in the history list by recalling them.
You can reissue a command with the r command. To reissue the last command, you simply type r. In the following example, I issue the command history 5 to view the last five commands from the history list. I then type r to reissue the last command, and again the last five commands are listed:
martyp $ history -5 301 whoami 302 pwd 303 more /etc/passwd 304 ps -efl 305 cat .profile 306 history -5 martyp $ r history -5 302 pwd 303 more /etc/passwd 304 ps -efl 305 cat .profile 306 history -5 307 history -5 martyp $
You can reissue a specific command number by typing r, a space, and the number of the command you wish to reissue. In the following example, I issue the history command number 302:
martyp $ history 294 history -5 295 whoami 296 pwd 297 more /etc/passwd 298 ps -efl 299 cat /etc/profile 300 history 5 301 whoami 302 pwd 303 more /etc/passwd 304 ps -efl 305 cat .profile 306 history -5 307 history -5 308 history -5 309 history martyp $ r 302 pwd /home/martyp martyp $
You can also give the name of the command you wish to reissue. Let's say that you want to reissue the last fc command. You would simply give the letter "f" along with the r command, and the last command that started with f would be reissued as shown in the following example:
martyp $ history 308 history -5 309 history 310 pwd 311 whoami 312 pwd 313 cat /etc/profile 314 ls 315 fc -l 316 env 317 who 318 cat /etc/passwd 319 ls -al 320 history 321 more .profile 322 set 323 history martyp $ r f fc -l 309 history 310 pwd 311 whoami 312 pwd 313 cat /etc/profile 314 ls 315 fc -l 316 env 317 who 318 cat /etc/passwd 319 ls -al 320 history 321 more .profile 322 set 323 history 324 fc -l martyp $
You can also perform some substitution with the r command. If you issued the vi command earlier and want to rerun vi but specify a different file name to edit, you can substitute a new file name. The following example shows reissuing an earlier vi command, except now we'll replace the original filename we edited, .profile, with the new filename we want to edit, .kshrc. In this example, we'll first run the history command, then reissue the vi command to edit .kshrc, and then we'll run the command again to see our revised vi command:
martyp $ history 316 env 317 who 318 cat /etc/passwd 319 ls -al 320 history 321 more .profile 322 set 323 history 324 fc -l 325 vi .profile 326 set 327 ls -al 328 env 329 who 330 more /etc/passwd | grep marty 331 history martyp $ r vi .profile=.kshrc martyp $ history 318 cat /etc/passwd 319 ls -al 320 history 321 more .profile 322 set 323 history 324 fc -l 325 vi .profile 326 set 327 ls -al 328 env 329 who 330 more /etc/passwd | grep marty 331 history 332 vi .kshrc 333 history martyp $
This command substitutes .kshrc for .profile on the command line.
This leads us to more advanced command-line editing. You may want to recall a command earlier issued and edit the command line using vi editor commands. The next section covers command-line editing.
You can edit entries in your history list with either the vi or emacs editor. I will cover the vi editor in this chapter, because it is the most widely used on UNIX systems. You can, however, perform all the same functions shown in this chapter with the emacs editor.
You edit the history list using vi the same way you edit a file using vi. You press the escape key and use standard vi keys for moving up and down, left and right, inserting deleting, and changing text. In this section, I cover fetching a command from the history list using vi commands and then I cover editing the command after you have restored it to the command line. After the command has been edited to your liking, you press enter to execute the command and place it at the very bottom of the command list.
Your editor is normally set in either your local .profile or /etc/profile. You can view these files to see what editor has been set for you by your system administrator. When I issue the env and set commands on my system, both report EDITOR=vi. This corresponds with my /etc/profile which has the editor set to vi.
Let's first take a look at fetching some previously issued commands using vi. The examples in this section use vi functionality that is described in both the vi chapter and on the vi quick reference card. The k, j, G, and search commands in this section operate in the same manner on the command line as they would if you were using vi to edit a file.
Pressing the escape key and a command allows you to perform various functions in the ksh. The following example shows producing the history list and issuing escape k to recall the previous command:
martyp $ history 125 man fc 126 set | more 127 exit 128 history 129 k 130 env | more 131 set | more 132 more .profile 133 more .profile | grep rof 134 more .profile | grep vi 135 more /etc/profile | grep vi 136 set |grep edit 137 set | grep vi 138 env | grep vi 139 history 140 who martyp $ history
Issuing escape k recalled the last command issued, in this case the who command at line 140. Each time you press k, the preceding ksh command is fetched. This is the same as pressing escape and the - (hyphen) key. You can specify the number of commands you wish to go back in the history list with escape nk, where n is the number of commands you want to go back in the history list. The following example shows issuing escape 5k to fetch the fifth command back in the history list:
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 commands that you may want to try at the command line.
After you have "fetched" the command you wish to edit or you have entered a command that needs editing, you can use your vi directives to make modifications on the command line.
The ksh puts you in input mode immediately upon fetching a command from the history list. This approach is the converse of the vi program that you use to edit files, which puts you in control mode by default. After you have fetched a command from the history list, you must press escape in order to move into control mode when using vi in ksh.
Let's now perform some simple modifications to commands we have fetched from the history list. We recall line number 286 from the history list with the sequence escape 286G. After recalling this command, we insert cat at the beginning of the command with i cat. i is for insert text to the left of the current cursor position. The following example shows the result of both the fetch of line 286 and inserting cat:
martyp $ history 285 history 286 more /etc/profile | grep vi 287 who 288 whoami 289 who 290 ls -al 291 alias 292 pwd 293 ls -al /home 294 cat .profile 295 history 296 vi .profile 297 cat /etc/passwd 298 cat /etc/passwd | grep donna 299 pwd 300 history martyp $ cat more /etc/profile | grep vi
You can see that i cat inserted cat at the very beginning of the line.
We can again recall line 286 and use A to append text to the very end of the line, as shown in the following example:
martyp $ history 285 history 286 more /etc/profile | grep vi 287 who 288 whoami 289 who 290 ls -al 291 alias 292 pwd 293 ls -al /home 294 cat .profile 295 history 296 vi .profile 297 cat /etc/passwd 298 cat /etc/passwd | grep donna 299 pwd 300 history martyp $ more /etc/profile | grep vieditor
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 of the vi commands I have covered here, as well as other commands to add, delete, change, search and replace, copy, and undo at the command line.
An alias is a name that you select for a frequently used command or series of commands. Many aliases are predefined for you.
The alias command, without any arguments, lists all aliases. This list includes both preset aliases as well as those you have set. The following command shows the preset aliases on the system on which I am working:
martyp $ alias
autoload='typeset -fu'
command='command '
functions='typeset -f'
history='fc -l'
hyper1=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc1;export HHLIC'
hyper36=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc36;export HHLIC'
hyper83=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc83;export HHLIC'
hyper95=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc95;export HHLIC'
integer='typeset -i'
local=typeset
nohup='nohup '
r='fc -e -'
stop='kill -STOP'
suspend='kill -STOP $$'
martyp $
Many preset aliases are shown as a result of typing the alias command without any options.
Many of these aliases are related to somewhat advanced use of the KornShell, such as job control. Others are useful to you right away. The history alias, for instance, lists the commands in the .sh_history file and precedes each entry by a line number. The r alias allows you to re-run the the last command that appears in the history list.
You are not limited to using only preset aliases. You can set your own aliases. The following example shows setting an alias, producing a list of aliases to see whether indeed our new alias has been set, and then running our alias:
martyp $ alias ls="ls -al" martyp $ alias autoload='typeset -fu' command='command ' functions='typeset -f' history='fc -l' hyper1=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc1;export HHLIC' hyper36=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc36;export HHLIC' hyper83=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc83;export HHLIC' hyper95=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc95;export HHLIC' integer='typeset -i' local=typeset ls='ls -al' nohup='nohup ' r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' martyp $ ls total 26 drwxr-xr-x 2 martyp staff 512 Mar 15 11:37. drwxrwxr-x 4 root sys 512 Mar 4 09:24 .. -rw-r--r-- 1 martyp staff 124 Mar 15 11:36 .cshrc -rw-r--r-- 1 martyp staff 562 Mar 4 09:24 .profile -rw------- 1 martyp staff 9058 Apr 10 06:58 .sh_history martyp $
The first command set an alias that executes ls -al whenever we type ls. I issued the alias command to see whether indeed the new alias would appear in the list of aliases. It appears right after local and right before nohup in the alphabetical list of aliases. The final command shows running ls, which produces the same listing that you would receive from running the ls -al command.
You don't have to keep an alias for the duration of your session after having set it. If you don't like an alias, you can use the unalias command to remove an alias.
To see unalias work, let's again produce a list of aliases, use unalias to unset the history alias, run the history command to see whether indeed it has been removed, and then run the fc -l command to which the history alias was mapped:
martyp $ alias autoload='typeset -fu' command='command ' functions='typeset -f' history='fc -l' hyper1=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc1;export HHLIC' hyper36=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc36;export HHLIC' hyper83=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc83;export HHLIC' hyper95=HHLIC='/opt/local/bristol/hyperhelp/licenses/hpptc95;export HHLIC' integer='typeset -i' local=typeset nohup='nohup ' r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' martyp $ unalias history martyp $ history ksh: history: not found martyp $ fc -l 131 ps 132 ls -alF 133 ls -al 134 alias ls="ls -al" 135 alias 136 ls 137 alias 138 unalias ls 139 ls 140 ls -al 141 alias 142 history 143 alias 144 unalias history 145 history 146 fc -l martyp $
When we unalias history and then run history, ksh is unable to find it and produces the message history: not found. When we run fc -l, a list of the most recently issued commands with their corresponding numbers is produced. This makes it clear that when you run the history alias, you are actually running the fc -l command.
ksh sometimes knows what you're thinking. You can type part of a command or pathname and ksh can complete the remainder for you. You can type part of a command or pathname and press the escape key to complete the command. If, for instance, you wish to issue the uname command to view the current system run level but can't remember the full command, you can type "un" and escape, followed by the "=" key, and the command is completed for you. In the following example, we'll change to the /sbin directory, list its contents, and then type 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 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 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 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 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 27-1 summarizes the command and path completion used in the previous examples:
In your general activities working with ksh, you have to perform a lot of file-name-related work, including crafting shell scripts that deal with file names. An overview of file name expansion is useful to ensure that you're comfortable with this topic before you start writing shell scripts.
Table 27-2 lists some common filename expansion and pattern matching commands:
Character(s) | Example | Description |
---|---|---|
* | 1) ls *.c | Match zero or more characters |
? | 2) ls conf.? | Match any single character |
[list] | 3) ls conf.[co] | Match any character in list |
[lower-upper] | 4) ls libdd.9873[5-6].sl | Match any character in range |
str{str1,str2,str3,...} | 5) ls ux*.{700,300} | Expand str with contents of {} |
~ | 6) ls -a ~ | Home directory |
~username | 7) ls -a ~gene | Home directory of username |
The following are more detailed descriptions of the examples shown in Table 27-2:
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 ~:
$ 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 27-3 shows many common forms of redirection.
As shown in Table 27-3, to redirect the output of a command from standard output to a file, you use ">". This works almost all of the time. If you have an environment variable called noclobber set, then redirecting to an existing file does not work (we'll cover environment variables shortly). The noclobber does not permit redirection to write over an existing file. If you try to write over an existing file, such as /tmp/processes below, you receive a message that the file exists:
# ps -ef > /tmp/processes
/tmp/processes: File exists
You can, however, use a "!" with redirection to force a file to be overwritten. Using ">!" forces a file to be overwritten, and ">>!" forces the output to be appended to the end of an existing file. Examples of these are shown in Table 27-3.
An environment variable is a name associated with a string. The name is the variable and the string is its value. Environment variables are also available to sub-shells or processes spawned by the shell. In most cases, you see environment variables capitalized, which is the convention on most systems.
When you issue a command on the system, you usually enter a relative pathname, not an absolute pathname. The command you issue is found because the PATH variable points to the location of directories where commands are located. Without this PATH variable, you would have to type the absolute pathname of every command you issue. When you issue a command, the shell searches the directories listed in the PATH variable in the order in which they are listed. A good way to see many of the environment variables you have set is with the env command as shown below:
martyp $ env
_=/usr/bin/env
MANPATH=:/opt/local/ptc/sysadmin/scripts:/opt/local/ptc/man:/opt/local/altrasofn
_INIT_UTS_RELEASE=5.7
HZ=100
_INIT_UTS_MACHINE=sun4m
EPC=true
PATH=/usr/bin:/usr/ucb:/etc:.
WEB_SERVER=sioux.rose.hp.com
_INIT_UTS_VERSION=Generic
MODEL=SPARCstation-10
OS_REV=5.7
EDITOR=vi
_INIT_RUN_NPREV=0
CLASSPATH=.:/usr/java/lib:
LOGNAME=martyp
_INIT_UTS_NODENAME=sunsys
_INIT_UTS_ISA=sparc
MAIL=/var/mail/martyp
ERASE=^H
OS=solaris
PS1=$PWD
$LOGNAME $TOKEN
_INIT_PREV_LEVEL=S
HOST=sunsys
TESTEXPERT_HOME=/opt/local/svn/te33
TA_HOME=/opt/local/platinum/solaris2/testadvise
MA_HOME=/opt/local/platinum/solaris2/memadvise
CL_LICENSE_FILE=/opt/local/CenterLine/configs/license.dat
SHELL=/bin/ksh
PROFILE_DIR=/opt/local/ptc/sysadmin/profile.d
OSTYPE=solaris2
HOME=/home/martyp
_INIT_UTS_SYSNAME=SunOS
TERM=vt100
LD_LIBRARY_PATH=:/opt/local/parasoft/lib.solaris
MWHOME=/opt/local/mainsoft/mainwin/mw
FMHOME=/opt/local/adobe/frame
PWD=/home/martyp
TZ=US/Pacific
_INIT_RUN_LEVEL=3
CLEARCASE_BLD_UMASK=02
_INIT_UTS_PLATFORM=SUNW,SPARCstation-10
martyp $
As you can see, other environment variables in addition to PATH make working on your UNIX system easier. You may want to issue other commmands related to ksh variables. Table 27-4 summarizes some ksh-related variable commands you may want to issue on your system.
Command | Description |
---|---|
env | Lists all environment variables (exported). These variables are normally uppercase and passed to child processes. |
set | Prints all local and exported set variables. |
set -o | Lists all built-in variables that are set to on or off. |
typeset | Displays all variables and associated attributes, functions, and integers. |
typeset + | Displays only the names of variables. |
You may want to try all these commands on your system to see what variables have been set for you.
If you want to know the value of a specific environment variable, you could use the echo command to see its value, as shown below for the environment variable HOME:
martyp $ echo $HOME
/home/martyp
Similarly, to view the operating system type on this specific computer, you could issue the following command:
martyp $ echo $OSTYPE
solaris2
The "$" preceding the environment variable name specifies that the value of the variable be sent to standard output. In this case, the value of the environment variable HOME is /home/martyp, which means that the current user has a home directory of /home/martyp.
You can define your own environment variables in ksh with the following syntax:
export NAME=value
Many users like to customize the ksh prompts. Most systems provide four ksh prompts by default. You can normally modify the first two prompts. The first, called PS1, is the primary prompt. The second, called PS2, appears after you have partially typed a command and pressed enter. PS1 is normally set to a $ and PS2 to >, by default.
The following example sets PS1 to our home directory, a space, the current history number, a space, and dollar sign:
We'll leave the default for PS2 as >. The following sequence shows issuing a command at our new PS1 prompt and the default PS2 prompt:
/home/martyp 187 $ print "This is new PS1 > but default PS2" This is new PS1 but default PS2 /home/martyp 188 $
This example shows the new PS1, including the history entry incrementing from 187 to 188, and the default PS2 when the incomplete print command was issued.
You can also append to the end of an existing variable with the following format:
export NAME="$NAME:appended_information"
To add /home/martyp/programs to the existing PATH environment variable, for instance, you issue the following command:
export PATH="$PATH:/home/martyp/programs"
This appends the path /home/martyp/programs to the environment variable PATH.
A great deal of flexibility is available when working with ksh. You should view all your variables and update those that make your job easier. Some customization, such as updating PS1 and your PATH, can also make your job easier.
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/ttsend.c
/usr/openwin/share/src/olit/oldials/oldials.c
/usr/openwin/share/src/olit/olitbook/ch10/draw.c
^Z[3] + Stopped (SIGTSTP) find /usr -name *.c
After ctrl-z is pressed, the find command is interrupted at the point at which you type ctrl-z. The command is suspended at this point, and you are shown the job number, in this case "3," and its status is listed as "Stopped". This command has only been suspended; it is not gone forever. You can start this process in the foreground with fg, or run it in the background with bg. Using bg runs the command as if you had followed it with an "&". It is started from the point at which you interrupted it. You do not have to supply a job number when you issue the fg or bg command, because the default is to perform the specified operation on the last job, which in this case is job number 3.
Notice that in this example we have stopped job number 3. This means that there are other jobs running with lower job numbers. You can use the jobs command to get a list of all jobs and their status. You can then control the jobs by issuing commands such as fg followed by a "%" and the job number to run the command in the foreground, or a bg followed by a "%" and the job number to run the command in the background. If you wish to terminate a job altogether, you can issue the kill command followed by a "%" and the job number.
In the process of creating the examples in this section, I have started and suspended many jobs. The following example shows listing all jobs with the jobs command, killing jobs 1 and 2 with kill, and running job 3 in the background:
martyp $ jobs [3] + Stopped (SIGTSTP) find /usr -name *.c [2] - Running time find / -name gnu* > gnu 2>&1 & [1] Running time find / -name *.c > cprogs 2>&1 & martyp $ kill %1 [1] Terminated time find / -name *.c > cprogs 2>&1 & martyp $ kill %2 [2] - Terminated time find / -name gnu* > gnu 2>&1 & martyp $ bg %3 [3] find /usr -name *.c& martyp $
Notice that an ampersand was added to job 3 when we requested that it be run in the background. Killing jobs 1 and 2 and running job 3 in the background returns the prompt so that you can perform additional work.
An additional topic to cover related to ksh is file permissions and the way they relate to umask. This is important because you may write shell programs, and the permissions control the access that others will have to these programs. umask is used to specify permission settings for new files and directories.
Let's start with an example of a long listing of a file. We'll use ls -l in the following example:
sys1 1: ls -l script1
-rwxr-xr-x 1 marty users 120 Jul 26 10:20 script1
The access rights for this file are defined by the position of read (r), write (w), and execute (x) when the ls -l command is issued. Figure 27-1 shows the three groups of three access rights for this file:
The owner of this file has read, write, and execute permissions on the file. The group to which the user belongs has read and execute permissions, and others also have read and execute permissions. The permissions on this file can be specified by the octal sum of each field, which is 755.
What happens if you craft a new shell script or any new file? What permission settings exist? You want to execute the shell script, so you need execute permission for the file. You can use umask to define the defaults for all your new files and directories.
By default, most systems start with a permission of 777 for directories and 666 for files. These mean that everyone has complete access to all directories you create and everyone has read and write access to all files you create. These defaults are modified with the value of umask.
You can view your umask in the following two ways:
martyp $ umask 002 martyp $ umask -S u=rwx,g=rwx,o=rx martyp $
The first example displays the octal value of umask, which we'll cover shortly, and the second example shows the symbolic value of umask.
The umask is used to disable access. You start with a umask and use the fields to disable some level of access. The umask command uses three octal fields. The fields are the sum of the access codes for user, group, and other as shown in Figure 27-2:
The complement of the umask field is "anded" with the default setting to change the umask. You can set umask by specifying its value. In our earlier example we viewed umask two different ways. To set the umask, you simply issue umask and the desired value. Setting umask to 022, for example, removes write permissions of directories for "group" and "other," as shown in Figure 27-3:
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 27-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.
Two means exist by which you can change the permissions: symbolic and numeric. I focus first on the numeric mode, because the numbers involved are easy to manage, and I sometimes find that new UNIX users get hung up on the meanings of some of the symbols. I'll then cover the symbols and include the symbol meanings in the chmod summary.
First of all, what do I mean by numbers? Looking at the numbers for sort, we see permissions of 751: 7 for owner (hundred's position), 5 for group (ten's position), and 1 for other (one's position). Figure 27-5 helps with the meanings of the positions:
Selecting the desired permissions for owner, group, and other, you use the chmod command to assign those permissions to a file or directory. Some of these permission possibilities are infrequently used, such as execute only, because you usually need to have read access to a file in order to execute it; however, I included all possibilities in Figure 27-5 for completeness. In addition to the permission mode bits shown in Figure 27-5, there are also miscellaneous mode bits, which you don't need to be concerned with at this time.
If you decide that you would like to add write permission of the file sort for group, and remove all permissions for other, you would simply execute the chmod command with the appropriate numeric value. The following set of commands first list the existing permissions for sort, next change the permissions on sort, and finally, list the new permissions on sort:
$ ls -l sort -rwxr-x--x 1 marty users 120 Jul 26 10:20 sort $ chmod 770 sort $ ls -l sort -rwxrwx--- 1 marty users 120 Jul 26 10:20 sort
The same set of commands to change the permissions using the symbolic mode would be:
$ ls -l sort -rwxr-x--x 1 marty users 120 Jul 26 10:20 sort $ chmod g+w,o-x sort $ ls -l sort -rwxrwx--- 1 marty users 120 Jul 26 10:20 sort
In symbolic mode, you issue the chmod command and specify who will be affected by the change [user (u), group (g), other (o), or all (a)], the operation you wish to perform [add (+), delete (-), or replace (=)], and the permission you wish to specify [read (r), write (w), or execute (x)]. In the previous example using symbolic mode, write (w) permission is being added (+) for group (g), and execute (x) permission is being removed (-) for other (o).
The following is a summary of some of the more commonly used symbols of chmod:
chmod - Change permissions of specified files using the following symbolic mode list.
Symbol of who is affected: | ||
u | User is affected. | |
g | Group is affected. | |
o | Other is affected. | |
a | All users are affected. | |
Operation to perform: | ||
+ | Add permission. | |
- | Remove permission. | |
= | Replace permission. | |
Permission specified: | ||
r | Read permission. | |
w | Write permission. | |
x | Execute permission. | |
u | Copy user permissions. | |
g | Copy group permissions. | |
o | Copy other permissions. |
3.133.142.193