Parent Directory
|
Revision Log
Revision 1 - (view) (download)
| 1 : | root | 1 | This is unix.info, produced by makeinfo version 4.0 from unix.texinfo. |
| 2 : | |||
| 3 : | |||
| 4 : | File: unix.info, Node: Pipes and redirection, Next: tee and script, Prev: Arrays, Up: C shell | ||
| 5 : | |||
| 6 : | Pipes and redirection in csh | ||
| 7 : | ============================ | ||
| 8 : | |||
| 9 : | The symbols | ||
| 10 : | < > >> << | & | ||
| 11 : | |||
| 12 : | have a special meaning in the shell. By default, most commands take | ||
| 13 : | their input from the file `stdin' (the keyboard) and write their output | ||
| 14 : | to the file `stdout' and their error messages to the file `stderr' | ||
| 15 : | (normally, both of these output files are defined to be the current | ||
| 16 : | terminal device `/dev/tty', or `/dev/console'). | ||
| 17 : | |||
| 18 : | `stdin', `stdout' and `stderr', known collectively as `stdio', can | ||
| 19 : | be redefined or _redirected_ so that information is taken from or sent | ||
| 20 : | to a different file. The output direction can be changed with the | ||
| 21 : | symbol `>'. For example, | ||
| 22 : | |||
| 23 : | echo testing > myfile | ||
| 24 : | |||
| 25 : | produces a file called `myfile' which contains the string `testing'. | ||
| 26 : | The single `>' (greater than) sign always creates a new file, whereas | ||
| 27 : | the double `>>' appends to the end of a file, if it already exists. So | ||
| 28 : | the first of the commands | ||
| 29 : | echo blah blah >> myfile | ||
| 30 : | echo Newfile > myfile | ||
| 31 : | |||
| 32 : | adds a second line to `myfile' after `testing', whereas the second | ||
| 33 : | command writes over `myfile' and ends up with just one line `Newfile'. | ||
| 34 : | |||
| 35 : | Now suppose we mistype a command | ||
| 36 : | ehco test > myfile | ||
| 37 : | |||
| 38 : | The command `ehco' does not exist and so the error message `ehco: | ||
| 39 : | Command not found' appears on the terminal. This error message was sent | ||
| 40 : | to _stderr_ - so even though we redirected output to a file, the error | ||
| 41 : | message appeared on the screen to tell us that an error occurred. Even | ||
| 42 : | this can be changed. `stderr' can also be redirected by adding an | ||
| 43 : | ampersand `&' character to the `>' symbol. The command | ||
| 44 : | ehco test >& myfile | ||
| 45 : | |||
| 46 : | results in the file `myfile' being created, containing the error | ||
| 47 : | message `ehco: Command not found'. | ||
| 48 : | |||
| 49 : | The input direction can be changed using the `<' symbol for example | ||
| 50 : | /bin/mail mark < message | ||
| 51 : | |||
| 52 : | would send the file `message' to the user `mark' by electronic mail. | ||
| 53 : | The mail program takes its input from the file instead of waiting for | ||
| 54 : | keyboard input. | ||
| 55 : | |||
| 56 : | There are some refinements to the redirection symbols. First of all, | ||
| 57 : | let us introduce the C-shell variable `noclobber'. If this variable is | ||
| 58 : | set with a command like | ||
| 59 : | set noclobber | ||
| 60 : | |||
| 61 : | then files will not be overwritten by the `>' command. If one tries to | ||
| 62 : | redirect output to an existing file, the following happens. | ||
| 63 : | unix% set noclobber | ||
| 64 : | unix% touch blah # create an empty file blah | ||
| 65 : | unix% echo test > blah | ||
| 66 : | blah: File exists. | ||
| 67 : | |||
| 68 : | If you are nervous about overwriting files, then you can set | ||
| 69 : | `noclobber' in your `.cshrc' file. `noclobber' can be overridden using | ||
| 70 : | the pling `!' symbol. So | ||
| 71 : | unix% set noclobber | ||
| 72 : | unix% touch blah # create an empty file blah | ||
| 73 : | unix% echo test >! blah | ||
| 74 : | |||
| 75 : | writes over the file `blah' even though `noclobber' is set. | ||
| 76 : | |||
| 77 : | Here are some other combinations of redirection symbols | ||
| 78 : | |||
| 79 : | `>>' | ||
| 80 : | Append, including `stderr' | ||
| 81 : | |||
| 82 : | `>>!' | ||
| 83 : | Append, ignoring `noclobber' | ||
| 84 : | |||
| 85 : | `>>&!' | ||
| 86 : | Append `stdout', `stderr', ignore `noclobber' | ||
| 87 : | |||
| 88 : | `<<' | ||
| 89 : | See below. | ||
| 90 : | |||
| 91 : | The last of these commands reads from the standard input until it finds | ||
| 92 : | a line which contains a word. It then feeds all of this input into the | ||
| 93 : | program concerned. For example, | ||
| 94 : | nexus% mail mark <<quit | ||
| 95 : | nexus 1> Hello mark | ||
| 96 : | nexus 2> Nothing much to say... | ||
| 97 : | nexus 2> so bye | ||
| 98 : | nexus 2> | ||
| 99 : | nexus 2> quit | ||
| 100 : | Sending mail... | ||
| 101 : | Mail sent! | ||
| 102 : | |||
| 103 : | The mail message contains all the lines up to, but not including | ||
| 104 : | `marker'. This method can also be used to print text verbatim from a | ||
| 105 : | file without using multiple echo commands. Inside a script one may | ||
| 106 : | write: | ||
| 107 : | |||
| 108 : | cat << "marker"; | ||
| 109 : | |||
| 110 : | MENU | ||
| 111 : | |||
| 112 : | 1) choice 1 | ||
| 113 : | 2) choice 2 | ||
| 114 : | ... | ||
| 115 : | |||
| 116 : | marker | ||
| 117 : | The `cat' command writes directly to `stdout' and the input is | ||
| 118 : | redirected and taken directly from the script file. | ||
| 119 : | |||
| 120 : | A very useful construction is the `pipe' facility. Using the `|' | ||
| 121 : | symbol one can feed the `stdout' of one program straight into the | ||
| 122 : | `stdin' of another program. Similarly with `|&' both `stdout' and | ||
| 123 : | `stderr' can be piped into the input of another program. This is very | ||
| 124 : | convenient. For instance, look up the following commands in the manual | ||
| 125 : | and try them. | ||
| 126 : | |||
| 127 : | ps aux | more | ||
| 128 : | echo 'Keep on sharpenin them there knives!' | mail henry | ||
| 129 : | vmstat 1 | head | ||
| 130 : | ls -l /etc | tail | ||
| 131 : | |||
| 132 : | Note that when piping both standard input and standard error to another | ||
| 133 : | program, the two files _do not mix synchronously_. Often `stderr' | ||
| 134 : | appears first. | ||
| 135 : | |||
| 136 : | |||
| 137 : | File: unix.info, Node: tee and script, Next: Command history, Prev: Pipes and redirection, Up: C shell | ||
| 138 : | |||
| 139 : | `tee' and `script' | ||
| 140 : | ================== | ||
| 141 : | |||
| 142 : | Occasionally you might want to have a copy of what you see on your | ||
| 143 : | terminal sent to a file. `tee' and `script' do this. For instance, | ||
| 144 : | find / -type l -print | tee myfile | ||
| 145 : | |||
| 146 : | sends a copy of the output of `find' to the file `myfile'. `tee' can | ||
| 147 : | split the output into as many files as you want: | ||
| 148 : | |||
| 149 : | COMMAND | tee FILE1 FILE2 .... | ||
| 150 : | |||
| 151 : | You can also choose to record the output an entire shell session using | ||
| 152 : | the `script' command. | ||
| 153 : | nexus% script mysession | ||
| 154 : | Script started, file is mysession | ||
| 155 : | |||
| 156 : | nexus% echo Big brother is scripting you | ||
| 157 : | Big brother is scripting you | ||
| 158 : | |||
| 159 : | nexus% exit | ||
| 160 : | exit | ||
| 161 : | Script done, file is mysession | ||
| 162 : | |||
| 163 : | The file `mysession' is a text file which contains a transcript of the | ||
| 164 : | session. | ||
| 165 : | |||
| 166 : | |||
| 167 : | File: unix.info, Node: Command history, Next: Command/filename completion, Prev: tee and script, Up: C shell | ||
| 168 : | |||
| 169 : | Command history | ||
| 170 : | =============== | ||
| 171 : | |||
| 172 : | The history feature in C-shell means that you do not have to type | ||
| 173 : | commands over and over again. In the `tcsh' version of the C shell, and | ||
| 174 : | the `bash' version of the Bourne shell, you can use the <UP ARROW> key | ||
| 175 : | to browse back through the list of commands you have typed previously. | ||
| 176 : | |||
| 177 : | In the normal C-shell (`csh') there are three main commands. | ||
| 178 : | `!!' | ||
| 179 : | Execute the last command again. | ||
| 180 : | |||
| 181 : | `!-3' | ||
| 182 : | Execute the third last command again. | ||
| 183 : | |||
| 184 : | `!4' | ||
| 185 : | Execute command number 4. | ||
| 186 : | |||
| 187 : | The first of these simply repeats the last command. The second | ||
| 188 : | counts backwards from the last command to three commands-ago. The final | ||
| 189 : | command gives an absolute number. The absolute command number can be | ||
| 190 : | seen by typing `history'. | ||
| 191 : | |||
| 192 : | |||
| 193 : | File: unix.info, Node: Command/filename completion, Next: Single and double quotes, Prev: Command history, Up: C shell | ||
| 194 : | |||
| 195 : | Command/filename completion | ||
| 196 : | =========================== | ||
| 197 : | |||
| 198 : | In the `tcsh' extension of the C-shell, you can save hours worth of | ||
| 199 : | typing errors by using the completion mechanism. This feature is based | ||
| 200 : | on the <TAB> key. | ||
| 201 : | |||
| 202 : | The idea is that if you type half a filename and press <TAB>, the | ||
| 203 : | shell will try to guess the remainder of the filename. It does this by | ||
| 204 : | looking at the files which match what you have already typed and trying | ||
| 205 : | to fill in the rest. If there are several files which match, the shell | ||
| 206 : | sounds the "bell" or beeps. You can then type <CTRL-D> to obtain a list | ||
| 207 : | of the possible alternatives. Here is an example: suppose you have | ||
| 208 : | just a single file in the current directory called | ||
| 209 : | `very_long_filename', typing | ||
| 210 : | |||
| 211 : | more <TAB> | ||
| 212 : | |||
| 213 : | results in the following appearing on the command line | ||
| 214 : | more very_long_filename | ||
| 215 : | |||
| 216 : | The shell was able to identify a unique file. Now suppose that you have | ||
| 217 : | two files called `very_long_filename' and `very_big_filename', typing | ||
| 218 : | more <TAB> | ||
| 219 : | |||
| 220 : | results in the following appearing on the command line | ||
| 221 : | more very_ | ||
| 222 : | |||
| 223 : | and the shell beeps, indicating that the choice was not unique and a | ||
| 224 : | decision is required. Next, you type <CTRL-D> to see which files you | ||
| 225 : | ahve to choose from and the shell lists them and returns you to the | ||
| 226 : | command line, exactly where you were. You now choose | ||
| 227 : | `very_long_filename' by typing `l'. This is enough to uniquely identify | ||
| 228 : | the file. Pressing the <TAB> key again results in | ||
| 229 : | more very_long_filename | ||
| 230 : | |||
| 231 : | on the screen. As long as you have written enough to select a file | ||
| 232 : | uniquely, the shell will be able to complete the name for you. | ||
| 233 : | |||
| 234 : | Completion also works on shell commands, but it is a little slower | ||
| 235 : | since the shell must serach through all the directories in the command | ||
| 236 : | path to complete commands. | ||
| 237 : | |||
| 238 : | |||
| 239 : | File: unix.info, Node: Single and double quotes, Next: Job control, Prev: Command/filename completion, Up: C shell | ||
| 240 : | |||
| 241 : | Single and double quotes | ||
| 242 : | ======================== | ||
| 243 : | |||
| 244 : | Two kinds of quotes can be used in shell apart from the backward | ||
| 245 : | quotes we mentioned above. The essential difference between them is | ||
| 246 : | that certain shell commands work inside _double_ quotes but not inside | ||
| 247 : | single quotes. For example | ||
| 248 : | |||
| 249 : | nexus% echo /etc/rc.* | ||
| 250 : | /etc/rc.boot /etc/rc.ip /etc/rc.local | ||
| 251 : | |||
| 252 : | nexus% echo "/etc/rc.*" | ||
| 253 : | /etc/rc.* | ||
| 254 : | |||
| 255 : | nexus% echo "`who am i` -- my name is $user ???" | ||
| 256 : | nexus!mark ttyp7 Jul 13 10:16 -- my name is mark ??? | ||
| 257 : | |||
| 258 : | nexus% echo '`who am i` -- my name is $user ???' | ||
| 259 : | `who am i` -- my name is $user ??? | ||
| 260 : | We see that the single quotes prevent _variable substitution_ and | ||
| 261 : | _sub-shells_. Wildcards do not work inside either single or double | ||
| 262 : | quotes. | ||
| 263 : | |||
| 264 : | |||
| 265 : | File: unix.info, Node: Job control, Next: Scripts with argumemts, Prev: Single and double quotes, Up: C shell | ||
| 266 : | |||
| 267 : | Job control, break key, `fg', `bg' | ||
| 268 : | ================================== | ||
| 269 : | |||
| 270 : | So far we haven't mentioned UNIX's ability to multitask. In the | ||
| 271 : | Bourne shell (`sh') there are no facilities for controlling several user | ||
| 272 : | processes (1). C-shell provides some commands for starting and stopping | ||
| 273 : | processes. These originate from the days before windows and X11, so | ||
| 274 : | some of them may seem a little old-fashioned. They are still very | ||
| 275 : | useful nonetheless. | ||
| 276 : | |||
| 277 : | Let's begin by looking at the commands which are true for any shell. | ||
| 278 : | Most programs are run in the _foreground_ or _interactively_. That | ||
| 279 : | means that they are connected to the standard input and send their | ||
| 280 : | output to the standard output. A program can be made to run in the | ||
| 281 : | background, if it does not need to use the standard I/O. For example, a | ||
| 282 : | program which generates output and sends it to a file could run in the | ||
| 283 : | background. In a window environment, programs which create their own | ||
| 284 : | windows can also be started as background processes, leaving standard | ||
| 285 : | I/O in the shell free. | ||
| 286 : | |||
| 287 : | _Background processes run independently of what you are doing in the | ||
| 288 : | foreground._ | ||
| 289 : | |||
| 290 : | * Menu: | ||
| 291 : | |||
| 292 : | * Processes and signals:: | ||
| 293 : | * Child processes and zombies:: | ||
| 294 : | * Builtins:: | ||
| 295 : | |||
| 296 : | ---------- Footnotes ---------- | ||
| 297 : | |||
| 298 : | (1) Newer versions of the Bourne shell, like the Korn shell and | ||
| 299 : | Bourne-again-shell do have these facilities. | ||
| 300 : | |||
| 301 : | |||
| 302 : | File: unix.info, Node: Processes and signals, Next: Child processes and zombies, Prev: Job control, Up: Job control | ||
| 303 : | |||
| 304 : | Unix Processes and BSD signals | ||
| 305 : | ------------------------------ | ||
| 306 : | |||
| 307 : | A background process is started using the special charcter `&' at | ||
| 308 : | the end of the command line. | ||
| 309 : | find / -name '*lib*' -print >& output & | ||
| 310 : | |||
| 311 : | The final `&' on the end of this line means that the job will be run in | ||
| 312 : | the background. Note that this is not confused with the redirection | ||
| 313 : | operator `>&' since it must be the last character on the line. The | ||
| 314 : | command above looks for any files in the system containing the string | ||
| 315 : | `lib' and writes the list of files to a file called `output'. This | ||
| 316 : | might be a useful way of searching for missing libraries which you want | ||
| 317 : | to include in your environment variable `LD_LIBRARY_PATH'. Searching | ||
| 318 : | the enire disk from the root directory `/' could take a long time, so | ||
| 319 : | it pays to run this in the background. | ||
| 320 : | |||
| 321 : | If we want to see what processes are running, we can use the `ps' | ||
| 322 : | command. `ps' without any arguments lists all of your processes, i.e. | ||
| 323 : | all processes owned by the user name you logged in with. `ps' takes | ||
| 324 : | many options, for instance `ps auxg' will list all processes in | ||
| 325 : | gruesome detail. (The "g" is for group, not gruesome!) `ps' reads the | ||
| 326 : | kernel's process tables directly. | ||
| 327 : | |||
| 328 : | Processes can be stopped and started, or killed one and for all. | ||
| 329 : | The `kill' command does this. There are, in fact, two versions of the | ||
| 330 : | `kill' command. One of them is built into the C-shell and the other is | ||
| 331 : | not. If you use the C-shell then you will never care about the | ||
| 332 : | difference. We shall nonetheless mention the special features of the | ||
| 333 : | C-shell built-ins below. The kill command takes a number called a | ||
| 334 : | _signal_ as an argument and another number called the _process | ||
| 335 : | identifier_ or _PID_ for short. Kill send signals to processes. Some | ||
| 336 : | of these are fatal and some are for information only. The two commands | ||
| 337 : | |||
| 338 : | kill -15 127 | ||
| 339 : | kill 127 | ||
| 340 : | |||
| 341 : | are identical. They both send signal 15 to PID 127. This is the normal | ||
| 342 : | _termination_ signal and it is often enough to stop any process from | ||
| 343 : | running. | ||
| 344 : | |||
| 345 : | Programs can choose to ignore certain signals by trapping signals | ||
| 346 : | with a special handler. One signal they cannot ignore is signal 9. | ||
| 347 : | |||
| 348 : | kill -9 127 | ||
| 349 : | |||
| 350 : | is a sure way of killing PID 127. Even though the process dies, it may | ||
| 351 : | not be removed from the kernel's process table if it has a parent (see | ||
| 352 : | next section). | ||
| 353 : | |||
| 354 : | Here is the complete list of unix signals which the kernel send to | ||
| 355 : | processes in different circumstances. | ||
| 356 : | |||
| 357 : | 1 "SIGHUP", /* hangup */ | ||
| 358 : | 2 "SIGINT", /* interrupt */ | ||
| 359 : | 3 "SIGQUIT", /* quit */ | ||
| 360 : | 4 "SIGILL", /* illegal instruction (not reset when caught) */ | ||
| 361 : | 5 "SIGTRAP", /* trace trap (not reset when caught) */ | ||
| 362 : | 6 "SIGIOT/SIGABRT", /* IOT instruction */ | ||
| 363 : | 7 "SIGEMT", /* EMT instruction */ | ||
| 364 : | 8 "SIGFPE", /* floating point exception */ | ||
| 365 : | 9 "SIGKILL", /* kill (cannot be caught or ignored) */ | ||
| 366 : | 10 "SIGBUS", /* bus error */ | ||
| 367 : | 11 "SIGSEGV", /* segmentation violation */ | ||
| 368 : | 12 "SIGSYS", /* bad argument to system call */ | ||
| 369 : | 13 "SIGPIPE", /* write on a pipe with no one to read it */ | ||
| 370 : | 14 "SIGALRM", /* alarm clock */ | ||
| 371 : | 15 "SIGTERM", /* software termination signal from kill */ | ||
| 372 : | 16 "SIGURG", /* urgent condition on IO channel */ | ||
| 373 : | 17 "SIGSTOP", /* sendable stop signal not from tty */ | ||
| 374 : | 18 "SIGTSTP", /* stop signal from tty */ | ||
| 375 : | 19 "SIGCONT", /* continue a stopped process */ | ||
| 376 : | 20 "SIGCHLD/SIGCLD", /* to parent on child stop or exit */ | ||
| 377 : | 21 "SIGTTIN", /* to readers pgrp upon background tty read */ | ||
| 378 : | 22 "SIGTTOU", /* like TTIN for output if (tp->t_local<OSTOP) */ | ||
| 379 : | 23 "SIGIO/SIGPOLL", /* input/output possible signal */ | ||
| 380 : | 24 "SIGXCPU", /* exceeded CPU time limit */ | ||
| 381 : | 25 "SIGXFSZ", /* exceeded file size limit */ | ||
| 382 : | 26 "SIGVTALRM", /* virtual time alarm */ | ||
| 383 : | 27 "SIGPROF", /* profiling time alarm */ | ||
| 384 : | 28 "SIGWINCH", /* window changed */ | ||
| 385 : | 29 "SIGLOST", /* resource lost (eg, record-lock lost) */ | ||
| 386 : | 30 "SIGUSR1", /* user defined signal 1 */ | ||
| 387 : | 31 "SIGUSR2" | ||
| 388 : | |||
| 389 : | We have already mentioned 15 and 9 which are the main signals for | ||
| 390 : | users. Signal 1, or `HUP' can be sent to certain programs by the | ||
| 391 : | superuser. For instance | ||
| 392 : | kill -1 <inetd> | ||
| 393 : | kill -HUP <inetd> | ||
| 394 : | |||
| 395 : | which forces `inetd' to reread its configuration file. Sometimes it is | ||
| 396 : | useful to _suspend_ a process temporarily and then _restart_ it later. | ||
| 397 : | kill -18 <PID> # suspend process <PID> | ||
| 398 : | kill -19 <PID> # resume process <PID> | ||
| 399 : | |||
| 400 : | |||
| 401 : | File: unix.info, Node: Child processes and zombies, Next: Builtins, Prev: Processes and signals, Up: Job control | ||
| 402 : | |||
| 403 : | Child Processes and zombies | ||
| 404 : | --------------------------- | ||
| 405 : | |||
| 406 : | When you start a process from a shell, regardless of whether it is a | ||
| 407 : | background process or a foreground process, the new process becomes a | ||
| 408 : | _child_ of the original shell. Remember that the shell is just a unix | ||
| 409 : | process itself. Moreover, if one of the children starts a new process | ||
| 410 : | then it will be a child of the child (a grandchild?)! Processes | ||
| 411 : | therefore form _hierachies_. Several children can have a common | ||
| 412 : | _parent_. | ||
| 413 : | |||
| 414 : | If we kill a parent, then (unless the child has detached itself from | ||
| 415 : | the parent) all of its children die too. If a child dies, the parent is | ||
| 416 : | not affected. Sometimes when a child is killed, it does not die but | ||
| 417 : | becomes "defunct" or a zombie process. This means that the child has a | ||
| 418 : | parent which is _waiting_ for it to finish. If the parent has not yet | ||
| 419 : | been informed that the child has died, for example because it has been | ||
| 420 : | suspended itself, then the dead child is not removed from the kernel's | ||
| 421 : | process table. When the parent wakes up and receives the message that | ||
| 422 : | the child has terminated, the process entry for the dead child can be | ||
| 423 : | removed. | ||
| 424 : | |||
| 425 : | |||
| 426 : | File: unix.info, Node: Builtins, Prev: Child processes and zombies, Up: Job control | ||
| 427 : | |||
| 428 : | C-shell builtins: `jobs', `kill', `fg',`bg', break key | ||
| 429 : | ------------------------------------------------------ | ||
| 430 : | |||
| 431 : | Now let's look at some commands which are built into the C-shell for | ||
| 432 : | starting and stopping processes. C-shell refers to user programs as | ||
| 433 : | `jobs' rather than processes - but there is no real difference. The | ||
| 434 : | added bonus of the C-shell is that each shell has a _job number_ in | ||
| 435 : | addition to its PID. The job numbers are simpler and are private for the | ||
| 436 : | shell, whereas the PIDs are assigned by the kernel and are often very | ||
| 437 : | large numbers which are difficult to to remember. When a command is | ||
| 438 : | executed in the shell, it is assigned a job number. If you never run any | ||
| 439 : | background jobs then there is only ever one job number: 1, since every | ||
| 440 : | job exits before the next one starts. However, if you run background | ||
| 441 : | tasks, then you can have several jobs "active" at any time. Moreover, by | ||
| 442 : | _suspending_ jobs, C-shell allows you to have several interactive | ||
| 443 : | programs running on the same terminal - the `fg' and `bg' commands | ||
| 444 : | allow you to move commands from the background to the foreground and | ||
| 445 : | vice-versa. | ||
| 446 : | |||
| 447 : | Take a look at the following shell session. | ||
| 448 : | nexus% emacs myfile & | ||
| 449 : | [1] 4990 | ||
| 450 : | nexus% | ||
| 451 : | |||
| 452 : | ( other commands ... , edit myfile and close emacs ) | ||
| 453 : | |||
| 454 : | |||
| 455 : | [1] Exit 70 emacs myfile | ||
| 456 : | |||
| 457 : | When a background job is done, the shell prints a message at a suitable | ||
| 458 : | moment between prompts. | ||
| 459 : | |||
| 460 : | [1] Done emacs myfile | ||
| 461 : | |||
| 462 : | This tells you that job number 1 finished normally. If the job exits | ||
| 463 : | abnormally then the word `Done' may be replaced by some other message. | ||
| 464 : | For instance, if you kill the job, it will say | ||
| 465 : | unix% kill %12 | ||
| 466 : | [12] Terminated textedit file | ||
| 467 : | |||
| 468 : | You can list the jobs you have running using the `jobs' command. The | ||
| 469 : | output looks something like | ||
| 470 : | [1] + Running textedit c.tex | ||
| 471 : | [3] Running textedit glossary.tex | ||
| 472 : | [4] Running textedit net.tex | ||
| 473 : | [5] Running textedit overview.tex | ||
| 474 : | [6] Running textedit perl.tex | ||
| 475 : | [7] Running textedit shell.tex | ||
| 476 : | [8] Running textedit sysadm.tex | ||
| 477 : | [9] Running textedit unix.tex | ||
| 478 : | [10] Running textedit x11.tex | ||
| 479 : | [11] - Running shelltool | ||
| 480 : | [15] Suspended emacs myfile | ||
| 481 : | |||
| 482 : | To suspend a program which you are running in the foreground you can | ||
| 483 : | type <CTRL-z> (this is like sending a `kill -18' signal from the | ||
| 484 : | keyboard). (1) You can suspend any number of programs and then | ||
| 485 : | restart them one at a time using `fg' and `bg'. If you want job 5 to be | ||
| 486 : | restarted in the foreground, you would type | ||
| 487 : | |||
| 488 : | fg %5 | ||
| 489 : | |||
| 490 : | When you have had enough of job 5, you can type CTRL-z to suspend it | ||
| 491 : | and then type | ||
| 492 : | |||
| 493 : | fg %6 | ||
| 494 : | |||
| 495 : | to activate job 6. Provided a job does not want to send output to | ||
| 496 : | `stdout', you can restart any job in the background, using a command | ||
| 497 : | like. | ||
| 498 : | bg %4 | ||
| 499 : | |||
| 500 : | _This method of working was useful before windows were available._ | ||
| 501 : | _Using `fg' and `bg', you can edit several files_ _or work on several | ||
| 502 : | programs without have to quit to_ _move from one to another._ | ||
| 503 : | |||
| 504 : | See also some related commands for batch processing `at', `batch' | ||
| 505 : | and `atq', `cron'. | ||
| 506 : | |||
| 507 : | NOTE: <CTRL-c> sends a `kill -2' signal, which send a standard | ||
| 508 : | interrupt message to a program. This is always a safe way to interrupt | ||
| 509 : | a shell command. | ||
| 510 : | |||
| 511 : | ---------- Footnotes ---------- | ||
| 512 : | |||
| 513 : | (1) This does not seem to work in solaris?! | ||
| 514 : | |||
| 515 : | |||
| 516 : | File: unix.info, Node: Scripts with argumemts, Next: subshells, Prev: Job control, Up: C shell | ||
| 517 : | |||
| 518 : | Scripts with arguments | ||
| 519 : | ====================== | ||
| 520 : | |||
| 521 : | One of the useful features of the shell is that you can use the | ||
| 522 : | normal unix commands to make programs called _scripts_. To make a | ||
| 523 : | script, you just create a file containing shell commands you want to | ||
| 524 : | execute and make sure that the first line of the file looks like the | ||
| 525 : | following example. | ||
| 526 : | |||
| 527 : | #!/bin/csh -f | ||
| 528 : | # | ||
| 529 : | # A simple script: check for user's mail | ||
| 530 : | # | ||
| 531 : | # | ||
| 532 : | |||
| 533 : | set path = ( /bin /usr/ucb ) # Set the local path | ||
| 534 : | |||
| 535 : | cd /var/spool/mail # Change dir | ||
| 536 : | |||
| 537 : | foreach uid ( * ) | ||
| 538 : | |||
| 539 : | echo "$uid has mail in the intray! " # space prevents an error! | ||
| 540 : | |||
| 541 : | end | ||
| 542 : | |||
| 543 : | The sequence `#!/bin/csh' means that the following commands are to | ||
| 544 : | be fed into `/bin/csh'. The two symbols `#!' must be the very first two | ||
| 545 : | characters in the file. The `-f' option means that your `.cshrc' file | ||
| 546 : | is not read by the shell when it starts up. The file containing this | ||
| 547 : | script must be executable (see `chmod') and must be in the current | ||
| 548 : | path, like all other programs. | ||
| 549 : | |||
| 550 : | Like C programs, C-shell scripts can accept command line arguments. | ||
| 551 : | Suppose you want to make a program to say hello to some other users who | ||
| 552 : | are logged onto the system. | ||
| 553 : | say-hello mark sarah mel | ||
| 554 : | |||
| 555 : | To do this you need to know the names that were typed on the command | ||
| 556 : | line. These names are copied into an array in the C-shell called the | ||
| 557 : | _argument vector_, or `argv'. To read these arguments, you just treat | ||
| 558 : | `argv' as an array. | ||
| 559 : | |||
| 560 : | #!/bin/csh -f | ||
| 561 : | # | ||
| 562 : | # Say hello | ||
| 563 : | # | ||
| 564 : | |||
| 565 : | foreach name ( $argv ) | ||
| 566 : | |||
| 567 : | echo Saying hello to $name | ||
| 568 : | echo "Hello from $user! " | write $name | ||
| 569 : | |||
| 570 : | end | ||
| 571 : | The elements of the array can be referred to as | ||
| 572 : | `argv[1]'..`argv[$#argv]' as usual. They can also be referred to as | ||
| 573 : | `$1'..`$3' upto the last acceptable number. This makes C-shell | ||
| 574 : | compatible with the Bourne shell as far as arguments are concerned. One | ||
| 575 : | extra flourish in this method is that you can also refer to the name of | ||
| 576 : | the program itself as `$0'. For example, | ||
| 577 : | #!/bin/csh -f | ||
| 578 : | |||
| 579 : | echo This is program $0 running for $user | ||
| 580 : | |||
| 581 : | `$argv' represents all the arguments. You can also use `$*' from the | ||
| 582 : | Bourne shell. | ||
| 583 : | |||
| 584 : | |||
| 585 : | File: unix.info, Node: subshells, Next: Tests and conditions, Prev: Scripts with argumemts, Up: C shell | ||
| 586 : | |||
| 587 : | Sub-shells () | ||
| 588 : | ============= | ||
| 589 : | |||
| 590 : | The C-shell does not allow you to define subroutines or functions, | ||
| 591 : | but you can create a local shell, with its own private variables by | ||
| 592 : | enclosing commands in parentheses. | ||
| 593 : | #!/bin/csh | ||
| 594 : | |||
| 595 : | cd /etc | ||
| 596 : | |||
| 597 : | ( cd /usr/bin; ls * ) > myfile | ||
| 598 : | |||
| 599 : | pwd | ||
| 600 : | This program changes the working directory to /etc and then executes | ||
| 601 : | a subshell which _inside the brackets_ changes directory to /usr/bin | ||
| 602 : | and lists the files there. The output of this private shell are sent to | ||
| 603 : | a file `myfile'. At the end we print out the current working directory | ||
| 604 : | just to show that the `cd' command in brackets had no effect on the | ||
| 605 : | main program. | ||
| 606 : | |||
| 607 : | Normally both parentheses must be on the same line. If a subshell | ||
| 608 : | command line gets too long, so that the brackets are not on the same | ||
| 609 : | line, you have to use backslash characters to continue the lines, | ||
| 610 : | |||
| 611 : | ( command \ | ||
| 612 : | command \ | ||
| 613 : | command \ | ||
| 614 : | ) | ||
| 615 : | |||
| 616 : | |||
| 617 : | File: unix.info, Node: Tests and conditions, Next: Loops in csh, Prev: subshells, Up: C shell | ||
| 618 : | |||
| 619 : | Tests and conditions | ||
| 620 : | ==================== | ||
| 621 : | |||
| 622 : | No programming language would be complete without tests and loops. | ||
| 623 : | C-shell has two kinds of decision structure: the `if..then..else' and | ||
| 624 : | the `switch' structure. These are closely related to their C | ||
| 625 : | counterparts. The syntax of these is | ||
| 626 : | if (CONDITION) COMMAND | ||
| 627 : | |||
| 628 : | if (CONDITION) then | ||
| 629 : | command | ||
| 630 : | command.. | ||
| 631 : | else | ||
| 632 : | command | ||
| 633 : | command.. | ||
| 634 : | endif | ||
| 635 : | |||
| 636 : | |||
| 637 : | switch (STRING) | ||
| 638 : | |||
| 639 : | case ONE: | ||
| 640 : | commands | ||
| 641 : | breaksw | ||
| 642 : | |||
| 643 : | case TWO: | ||
| 644 : | commands | ||
| 645 : | breaksw | ||
| 646 : | |||
| 647 : | ... | ||
| 648 : | |||
| 649 : | endsw | ||
| 650 : | |||
| 651 : | In the latter case, no commands should appear on the same line as a | ||
| 652 : | `case' statement, or they will be ignored. Also, if the `breaksw' | ||
| 653 : | commands are omitted, then control flows through all the commands for | ||
| 654 : | case 2, case 3 etc, exactly as it does in the C programming language. | ||
| 655 : | |||
| 656 : | We shall consider some examples of these statements in a moment, but | ||
| 657 : | first it is worth listing some important tests which can be used in | ||
| 658 : | `if' questions to find out information about files. | ||
| 659 : | |||
| 660 : | `-r FILE' | ||
| 661 : | True if the file exists and is readable | ||
| 662 : | |||
| 663 : | `-w FILE' | ||
| 664 : | True if the file exists and is writable | ||
| 665 : | |||
| 666 : | `-x FILE' | ||
| 667 : | True if the file exists and is executable | ||
| 668 : | |||
| 669 : | `-e FILE' | ||
| 670 : | True if the file simply exists | ||
| 671 : | |||
| 672 : | `-z FILE' | ||
| 673 : | True if the file exists and is empty | ||
| 674 : | |||
| 675 : | `-f FILE' | ||
| 676 : | True if the file is a plain file | ||
| 677 : | |||
| 678 : | `-d FILE' | ||
| 679 : | True if the file is a directory | ||
| 680 : | |||
| 681 : | We shall also have need of the following comparision operators. | ||
| 682 : | |||
| 683 : | `==' | ||
| 684 : | is equal to (string comparison) | ||
| 685 : | |||
| 686 : | `!=' | ||
| 687 : | is not equal to | ||
| 688 : | |||
| 689 : | `>' | ||
| 690 : | is greater than | ||
| 691 : | |||
| 692 : | `<' | ||
| 693 : | is less than | ||
| 694 : | |||
| 695 : | `>=' | ||
| 696 : | is greater than or equal to | ||
| 697 : | |||
| 698 : | `<=' | ||
| 699 : | is less than or equal to | ||
| 700 : | |||
| 701 : | `=~' | ||
| 702 : | matches a wildcard | ||
| 703 : | |||
| 704 : | `!~' | ||
| 705 : | does not match a wildcard | ||
| 706 : | |||
| 707 : | The simplest way to learn about these statements is to use them, so | ||
| 708 : | we shall now look at some examples. | ||
| 709 : | |||
| 710 : | #!/bin/csh -f | ||
| 711 : | # | ||
| 712 : | # Safe copy from <arg[1]> to <arg[2]> | ||
| 713 : | # | ||
| 714 : | # | ||
| 715 : | |||
| 716 : | if ($#argv != 2) then | ||
| 717 : | |||
| 718 : | echo "Syntax: copy <from-file> <to-file>" | ||
| 719 : | exit 0 | ||
| 720 : | |||
| 721 : | endif | ||
| 722 : | |||
| 723 : | if ( -f $argv[2] ) then | ||
| 724 : | |||
| 725 : | echo "File exists. Copy anyway?" | ||
| 726 : | |||
| 727 : | switch ( $< ) # Get a line from user | ||
| 728 : | |||
| 729 : | case y: | ||
| 730 : | breaksw | ||
| 731 : | |||
| 732 : | default: | ||
| 733 : | echo "Doing nothing!" | ||
| 734 : | exit 0 | ||
| 735 : | |||
| 736 : | endsw | ||
| 737 : | |||
| 738 : | endif | ||
| 739 : | |||
| 740 : | echo -n "Copying $argv[1] to $argv[2]..." | ||
| 741 : | cp $argv[1] $argv[2] | ||
| 742 : | echo done | ||
| 743 : | |||
| 744 : | endif | ||
| 745 : | |||
| 746 : | This script tries to copy a file from one location to another. If the | ||
| 747 : | user does not type exactly two arguments, the script quits with a | ||
| 748 : | message about the correct syntax. Otherwise it tests to see whether a | ||
| 749 : | plain file has the same name as the file the user wanted to copy to. If | ||
| 750 : | such a file exists, it asks the user if he/she wants to continue before | ||
| 751 : | proceding to copy. | ||
| 752 : | |||
| 753 : | * Menu: | ||
| 754 : | |||
| 755 : | * Switch example:: | ||
| 756 : | |||
| 757 : | |||
| 758 : | File: unix.info, Node: Switch example, Prev: Tests and conditions, Up: Tests and conditions | ||
| 759 : | |||
| 760 : | Switch example: configure script | ||
| 761 : | -------------------------------- | ||
| 762 : | |||
| 763 : | Here is another example which compiles a software package. This is | ||
| 764 : | a problem we shall return to later *Note Make::. The problem this | ||
| 765 : | script tries to address is the following. There are many different | ||
| 766 : | versions of UNIX and they are not exactly compatible with one another. | ||
| 767 : | The program this file compiles has to work on any kind of UNIX, so it | ||
| 768 : | tries first to determine what kind of UNIX system the script is being | ||
| 769 : | run on by calling `uname'. Then it defines a variable `MAKE' which | ||
| 770 : | contains the path to the `make' program which will build _software_. | ||
| 771 : | The make program reads a file called `Makefile' which contains | ||
| 772 : | instructions for compiling the program, but this file needs to know the | ||
| 773 : | type of UNIX, so the script first copies a file `Makefile.src' using | ||
| 774 : | `sed' replace a dummy string with the real name of the UNIX. Then it | ||
| 775 : | calls make and sets the correct permission on the file using `chmod'. | ||
| 776 : | |||
| 777 : | #!/bin/csh -f | ||
| 778 : | ################################################# | ||
| 779 : | # | ||
| 780 : | # | ||
| 781 : | # CONFIGURE Makefile AND BUILD software | ||
| 782 : | # | ||
| 783 : | # | ||
| 784 : | ################################################# | ||
| 785 : | |||
| 786 : | set NAME = ( `uname -r -s` ) | ||
| 787 : | |||
| 788 : | switch ($NAME[1]) | ||
| 789 : | |||
| 790 : | case SunOS*: | ||
| 791 : | switch ($NAME[2]) | ||
| 792 : | |||
| 793 : | case 4*: | ||
| 794 : | setenv TYPE SUN4 | ||
| 795 : | setenv MAKE /bin/make | ||
| 796 : | breaksw | ||
| 797 : | case 5*: | ||
| 798 : | setenv TYPE SOLARIS | ||
| 799 : | setenv MAKE /usr/ccs/bin/make | ||
| 800 : | breaksw | ||
| 801 : | |||
| 802 : | endsw | ||
| 803 : | breaksw | ||
| 804 : | |||
| 805 : | case ULTRIX*: | ||
| 806 : | setenv TYPE ULTRIX | ||
| 807 : | setenv MAKE /bin/make | ||
| 808 : | breaksw | ||
| 809 : | case HP-UX*: | ||
| 810 : | setenv TYPE HPuUX | ||
| 811 : | setenv MAKE /bin/make | ||
| 812 : | breaksw | ||
| 813 : | case AIX*: | ||
| 814 : | setenv TYPE AIX | ||
| 815 : | setenv MAKE /bin/make | ||
| 816 : | breaksw | ||
| 817 : | |||
| 818 : | case OSF*: | ||
| 819 : | setenv TYPE OSF | ||
| 820 : | setenv MAKE /bin/make | ||
| 821 : | breaksw | ||
| 822 : | case IRIX*: | ||
| 823 : | setenv TYPE IRIX | ||
| 824 : | setenv MAKE /bin/make | ||
| 825 : | breaksw | ||
| 826 : | |||
| 827 : | default: | ||
| 828 : | echo Unknown architecture $NAME[1] | ||
| 829 : | |||
| 830 : | endsw | ||
| 831 : | |||
| 832 : | # Generate Makefile from source file | ||
| 833 : | |||
| 834 : | sed s/HOSTTYPE/$TYPE/ Makefile.src > Makefile | ||
| 835 : | |||
| 836 : | echo "Making software. Type CTRL-C to abort and edit Makefile" | ||
| 837 : | |||
| 838 : | $MAKE software # call make to build program | ||
| 839 : | chmod 755 software # set correct protection | ||
| 840 : | |||
| 841 : | |||
| 842 : | File: unix.info, Node: Loops in csh, Next: Input from the user, Prev: Tests and conditions, Up: C shell | ||
| 843 : | |||
| 844 : | Loops in csh | ||
| 845 : | ============ | ||
| 846 : | |||
| 847 : | The C-shell has three loop structures: `repeat', `while' and | ||
| 848 : | `foreach'. We have already seen some examples of the `foreach' loop. | ||
| 849 : | |||
| 850 : | The structure of these loops is as follows | ||
| 851 : | repeat NUMBER-OF-TIMES COMMAND | ||
| 852 : | |||
| 853 : | |||
| 854 : | while ( TEST EXPRESSION ) | ||
| 855 : | |||
| 856 : | COMMANDS | ||
| 857 : | |||
| 858 : | end | ||
| 859 : | |||
| 860 : | |||
| 861 : | foreach CONTROL-VARIABLE ( LIST-OR-ARRAY ) | ||
| 862 : | |||
| 863 : | COMMANDS | ||
| 864 : | |||
| 865 : | end | ||
| 866 : | |||
| 867 : | The commands `break' and `continue' can be used to break out of the | ||
| 868 : | loops at any time. Here are some examples. | ||
| 869 : | |||
| 870 : | repeat 2 echo "Yo!" | write mark | ||
| 871 : | |||
| 872 : | This sends the message "Yo!" to mark's terminal twice. | ||
| 873 : | repeat 5 echo `echo "Shutdown time! Log out now" | wall ; sleep 30` ; halt | ||
| 874 : | |||
| 875 : | This example repeats the command `echo Shutdown time...' five times at | ||
| 876 : | 30 second intervals, before shutting down the system. Only the | ||
| 877 : | superuser can run this command! Note the strange construction with | ||
| 878 : | `echo echo'. This is to force the repeat command to take two shell | ||
| 879 : | commands as an argument. (Try to explain why this works for yourself.) | ||
| 880 : | |||
| 881 : | |||
| 882 : | File: unix.info, Node: Input from the user, Next: Extracting parts of a pathname, Prev: Loops in csh, Up: C shell | ||
| 883 : | |||
| 884 : | Input from the user | ||
| 885 : | =================== | ||
| 886 : | |||
| 887 : | |||
| 888 : | # Test a user response | ||
| 889 : | |||
| 890 : | echo "Answer y/n (yes or no)" | ||
| 891 : | |||
| 892 : | set valid = false | ||
| 893 : | |||
| 894 : | while ( $valid == false ) | ||
| 895 : | |||
| 896 : | switch ( $< ) | ||
| 897 : | |||
| 898 : | case y: | ||
| 899 : | echo "You answered yes" | ||
| 900 : | set valid = true | ||
| 901 : | breaksw | ||
| 902 : | |||
| 903 : | case n: | ||
| 904 : | echo "You answered no" | ||
| 905 : | set valid = true | ||
| 906 : | breaksw | ||
| 907 : | |||
| 908 : | default: | ||
| 909 : | echo "Invalid reponse, try again" | ||
| 910 : | breaksw | ||
| 911 : | |||
| 912 : | endsw | ||
| 913 : | |||
| 914 : | end | ||
| 915 : | |||
| 916 : | Notice that it would have been simpler to replace the two lines | ||
| 917 : | set valid = true | ||
| 918 : | breaksw | ||
| 919 : | |||
| 920 : | by a single line `break'. `breaksw' jumps out of the switch | ||
| 921 : | construction, after which the `while' test fails. `break' jumps out of | ||
| 922 : | the entire while loop. | ||
| 923 : | |||
| 924 : | |||
| 925 : | File: unix.info, Node: Extracting parts of a pathname, Next: Arithmetic, Prev: Input from the user, Up: C shell | ||
| 926 : | |||
| 927 : | Extracting parts of a pathname | ||
| 928 : | ============================== | ||
| 929 : | |||
| 930 : | A path name consists of a number of different parts: | ||
| 931 : | * The path to the directory where a file is held. | ||
| 932 : | |||
| 933 : | * The name of the file itself. | ||
| 934 : | |||
| 935 : | * The file extension (after a dot). | ||
| 936 : | |||
| 937 : | By using one of the following modifiers, we can extract these | ||
| 938 : | different elements. | ||
| 939 : | |||
| 940 : | `:h' | ||
| 941 : | The path to the file | ||
| 942 : | |||
| 943 : | `:t' | ||
| 944 : | The filename itself | ||
| 945 : | |||
| 946 : | `:e' | ||
| 947 : | The file extension | ||
| 948 : | |||
| 949 : | `:r' | ||
| 950 : | The complete file-path minus the file extension | ||
| 951 : | |||
| 952 : | Here are some examples and the results: | ||
| 953 : | set f = ~/progs/c++/test.C | ||
| 954 : | |||
| 955 : | echo $f:h | ||
| 956 : | |||
| 957 : | /home/mark/progs/c++ | ||
| 958 : | |||
| 959 : | echo $f:t | ||
| 960 : | |||
| 961 : | test.C | ||
| 962 : | |||
| 963 : | echo $f:e | ||
| 964 : | |||
| 965 : | C | ||
| 966 : | echo $f:r | ||
| 967 : | |||
| 968 : | /home/mark/progs/c++/test | ||
| 969 : | |||
| 970 : | |||
| 971 : | File: unix.info, Node: Arithmetic, Next: Examples, Prev: Extracting parts of a pathname, Up: C shell | ||
| 972 : | |||
| 973 : | Arithmetic | ||
| 974 : | ========== | ||
| 975 : | |||
| 976 : | Before using these features in a real script, we need one more | ||
| 977 : | possibility: numerical addition, subtraction and multiplication etc. | ||
| 978 : | |||
| 979 : | To tell the C-shell that you want to perform an operation on numbers | ||
| 980 : | rather than strings, you use the `@' symbol followed by a space. Then | ||
| 981 : | the following operations are possible. | ||
| 982 : | @ var = 45 # Assign a numerical value to var | ||
| 983 : | echo $var # Print the value | ||
| 984 : | |||
| 985 : | @ var = $var + 34 # Add 34 to var | ||
| 986 : | @ var += 34 # Add 34 to var | ||
| 987 : | |||
| 988 : | @ var -= 1 # subtract 1 from var | ||
| 989 : | @ var *= 5 # Multiply var by 5 | ||
| 990 : | |||
| 991 : | @ var /= 3 # Divide var by 3 (integer division) | ||
| 992 : | @ var %= 3 # Remainder after dividing var by 3 | ||
| 993 : | |||
| 994 : | @ var++ # Increment var by 1 | ||
| 995 : | @ var-- # Decrement var by 1 | ||
| 996 : | |||
| 997 : | @ array[1] = 5 # Numerical array | ||
| 998 : | |||
| 999 : | @ logic = ( $x > 6 && $x < 10) # AND | ||
| 1000 : | @ logic = ( $x > 6 || $x < 10) # OR | ||
| 1001 : | @ false = ! $var # Logical NOT | ||
| 1002 : | |||
| 1003 : | @ bits = ( $x | $y ) # Bitwise OR | ||
| 1004 : | @ bits = ( $x ^ $y ) # Bitwise XOR | ||
| 1005 : | @ bits = ( $x & $y ) # Bitwise AND | ||
| 1006 : | |||
| 1007 : | @ shifted = ( $var >> 2 ) # Bitwise shift right | ||
| 1008 : | @ back = ( $var << 2 ) # Bitwise shift left | ||
| 1009 : | These operators are precisely those found in the C programming | ||
| 1010 : | language. | ||
| 1011 : | |||
| 1012 : | |||
| 1013 : | File: unix.info, Node: Examples, Prev: Arithmetic, Up: C shell | ||
| 1014 : | |||
| 1015 : | Examples | ||
| 1016 : | ======== | ||
| 1017 : | |||
| 1018 : | The following script uses the operators in the last two sections to | ||
| 1019 : | take a list of files with a given file extension (say `.doc') and | ||
| 1020 : | change it for another (say `.tex'). This is a partial solution to the | ||
| 1021 : | limitation of not being able to do multiple renames in shell. | ||
| 1022 : | |||
| 1023 : | #!/bin/csh -f | ||
| 1024 : | ############################################################# | ||
| 1025 : | # | ||
| 1026 : | # Change file extension for multiple files | ||
| 1027 : | # | ||
| 1028 : | ############################################################# | ||
| 1029 : | |||
| 1030 : | if ($#argv < 2) then | ||
| 1031 : | echo Syntax: chext oldpattern newextension | ||
| 1032 : | echo "e.g: chext *.doc tex " | ||
| 1033 : | exit 0 | ||
| 1034 : | endif | ||
| 1035 : | |||
| 1036 : | mkdir /tmp/chext.$user # Make a scratch area | ||
| 1037 : | |||
| 1038 : | set newext="$argv[$#argv]" # Last arg is new ext | ||
| 1039 : | set oldext="$argv[1]:e" | ||
| 1040 : | |||
| 1041 : | echo "Old extenstion was ($oldext)"" | ||
| 1042 : | echo "New extension ($newext) -- okay? (y/n)" | ||
| 1043 : | |||
| 1044 : | switch( $< ) | ||
| 1045 : | |||
| 1046 : | case y: | ||
| 1047 : | breaksw | ||
| 1048 : | default: | ||
| 1049 : | echo "Nothing done." | ||
| 1050 : | exit 0 | ||
| 1051 : | endsw | ||
| 1052 : | |||
| 1053 : | |||
| 1054 : | ############################################################## | ||
| 1055 : | # Remove the last file extension from files | ||
| 1056 : | ############################################################## | ||
| 1057 : | |||
| 1058 : | i = 0 | ||
| 1059 : | |||
| 1060 : | foreach file ($argv) | ||
| 1061 : | |||
| 1062 : | i++ | ||
| 1063 : | if ( $i == $#argv ) break | ||
| 1064 : | cp $file /tmp/chext.$user/$file:r # temporary store | ||
| 1065 : | |||
| 1066 : | end | ||
| 1067 : | |||
| 1068 : | ############################################################### | ||
| 1069 : | # Add .newext file extension to files | ||
| 1070 : | ############################################################### | ||
| 1071 : | |||
| 1072 : | set array = (`ls /tmp/chext.$user`) | ||
| 1073 : | |||
| 1074 : | foreach file ($array) | ||
| 1075 : | |||
| 1076 : | if ( -f $file.$newext ) then | ||
| 1077 : | echo destination file $file.$newext exists. No action taken. | ||
| 1078 : | continue | ||
| 1079 : | endif | ||
| 1080 : | |||
| 1081 : | cp /tmp/chext.$user/$file $file.$newext | ||
| 1082 : | rm $file.$oldext | ||
| 1083 : | |||
| 1084 : | end | ||
| 1085 : | |||
| 1086 : | rm -r /tmp/chext.$user | ||
| 1087 : | |||
| 1088 : | Here is another example to try to decipher. Use the manual pages to | ||
| 1089 : | find out about `awk'. This script can be written much more easily in | ||
| 1090 : | Perl or C, as we shall see in the next chapters. It is also trivially | ||
| 1091 : | implemented as a script in the system administration language cfengine. | ||
| 1092 : | |||
| 1093 : | #!/bin/csh -f | ||
| 1094 : | ########################################################### | ||
| 1095 : | # | ||
| 1096 : | # KILL all processes owned by $argv[1] with PID > $argv[2] | ||
| 1097 : | # | ||
| 1098 : | ########################################################### | ||
| 1099 : | |||
| 1100 : | |||
| 1101 : | if ("`whoami`" != "root") then | ||
| 1102 : | echo Permission denied | ||
| 1103 : | exit 0 | ||
| 1104 : | endif | ||
| 1105 : | |||
| 1106 : | if ( $#argv < 1 || $#argv > 2 ) then | ||
| 1107 : | echo Usage: KILL username lowest-pid | ||
| 1108 : | exit 0 | ||
| 1109 : | endif | ||
| 1110 : | |||
| 1111 : | if ( $argv[1] == "root") then | ||
| 1112 : | echo No! Too dangerous -- system will crash | ||
| 1113 : | exit 0 | ||
| 1114 : | endif | ||
| 1115 : | |||
| 1116 : | ############################################################ | ||
| 1117 : | # Kill everything | ||
| 1118 : | ############################################################ | ||
| 1119 : | |||
| 1120 : | if ( $#argv == 1 ) then | ||
| 1121 : | |||
| 1122 : | set killarray = ( `ps aux | awk '{ if ($1 == user) \ | ||
| 1123 : | {printf "%s ",$2}}' user=$argv[1]` ) | ||
| 1124 : | |||
| 1125 : | foreach process ($killarray) | ||
| 1126 : | |||
| 1127 : | kill -1 $process | ||
| 1128 : | kill -15 $process > /dev/null | ||
| 1129 : | kill -9 $process > /dev/null | ||
| 1130 : | |||
| 1131 : | if ("`kill -9 $process | egrep -e 'No such process'`" == "") then | ||
| 1132 : | echo "Warning - $process would not die - try again" | ||
| 1133 : | endif | ||
| 1134 : | end | ||
| 1135 : | |||
| 1136 : | ############################################################# | ||
| 1137 : | # Start from a certain PID | ||
| 1138 : | ############################################################# | ||
| 1139 : | |||
| 1140 : | else if ( $#argv == 2 ) then | ||
| 1141 : | |||
| 1142 : | set killarray = ( `ps aux | awk '{ if ($1 == user && $2 > uid) \ | ||
| 1143 : | {printf "%s ",$2}}' user=$argv[1] uid=$argv[2]` ) | ||
| 1144 : | |||
| 1145 : | foreach process ($killarray) | ||
| 1146 : | |||
| 1147 : | kill -1 $process > /dev/null | ||
| 1148 : | kill -15 $process | ||
| 1149 : | sleep 2 | ||
| 1150 : | kill -9 $process > /dev/null | ||
| 1151 : | |||
| 1152 : | if ("`kill -9 $process | egrep -e 'No such process'`" == "") then | ||
| 1153 : | echo "Warning - $process would not die - try again" | ||
| 1154 : | endif | ||
| 1155 : | end | ||
| 1156 : | |||
| 1157 : | endif | ||
| 1158 : | |||
| 1159 : | This program would be better written in C or Perl. | ||
| 1160 : | |||
| 1161 : | |||
| 1162 : | File: unix.info, Node: Bourne shell, Next: Perl, Prev: C shell, Up: Top | ||
| 1163 : | |||
| 1164 : | Bourne shell | ||
| 1165 : | ************ | ||
| 1166 : | |||
| 1167 : | Programmers who are used to C or C++ often find it easier to program | ||
| 1168 : | in C-shell because there are strong similarities between the two. The | ||
| 1169 : | Bourne shell is somewhat different in style, but is structured in a way | ||
| 1170 : | which makes it better suited to more complicated script writing, | ||
| 1171 : | especially for system administrators. Also it is closer to the kernels | ||
| 1172 : | own exec mechanism. The Bourne shell allows subroutines and default | ||
| 1173 : | values for parameters. Most of the system scripts in UNIX are written in | ||
| 1174 : | the Bourne shell. | ||
| 1175 : | |||
| 1176 : | The principles of the Bourne shell are largely the same as those for | ||
| 1177 : | the C-shell, so we shall skip fairly quickly through the details. | ||
| 1178 : | Historically, the Bourne shell came before the C shell. | ||
| 1179 : | |||
| 1180 : | * Menu: | ||
| 1181 : | |||
| 1182 : | * .profile:: | ||
| 1183 : | * Variables and export:: | ||
| 1184 : | * stdin stdout stderr:: | ||
| 1185 : | * Arithmetic in sh:: | ||
| 1186 : | * Scripts and arguments:: | ||
| 1187 : | * Return codes:: | ||
| 1188 : | * Tests in sh:: | ||
| 1189 : | * Input in sh:: | ||
| 1190 : | * Loops in sh:: | ||
| 1191 : | * Procedures and traps:: | ||
| 1192 : | * setuid setgid scripts:: | ||
| 1193 : | * Limitations of shell:: | ||
| 1194 : | * Ex4:: | ||
| 1195 : | |||
| 1196 : | |||
| 1197 : | File: unix.info, Node: .profile, Next: Variables and export, Prev: Bourne shell, Up: Bourne shell | ||
| 1198 : | |||
| 1199 : | .profile | ||
| 1200 : | ======== | ||
| 1201 : | |||
| 1202 : | The `.profile' file is the Bourne shell's answer to `.cshrc'. This | ||
| 1203 : | file is read by interactive `/bin/sh' shells on starting up. On Sun | ||
| 1204 : | systems the file `/etc/profile' is also read. On `HPUX' machines, the | ||
| 1205 : | file `/etc/src.sh' is read. | ||
| 1206 : | |||
| 1207 : | |||
| 1208 : | File: unix.info, Node: Variables and export, Next: stdin stdout stderr, Prev: .profile, Up: Bourne shell | ||
| 1209 : | |||
| 1210 : | Variables and export | ||
| 1211 : | ==================== | ||
| 1212 : | |||
| 1213 : | Local and global variables are both defined using the syntax | ||
| 1214 : | VARIABLE="Some string" | ||
| 1215 : | VAR=13 | ||
| 1216 : | |||
| 1217 : | It is important that there be no space between the variable and the | ||
| 1218 : | equals sign. By default these variables are _local_. To make them | ||
| 1219 : | global (so that child processes will inherit them) we use the command | ||
| 1220 : | export VARIABLE | ||
| 1221 : | |||
| 1222 : | This adds the variable to the process _environment_. It is the analogue | ||
| 1223 : | of making `environment variables' with `setenv' in C shell. The command | ||
| 1224 : | set -a | ||
| 1225 : | |||
| 1226 : | changes the default so that all variables, after the command are | ||
| 1227 : | created _global_. | ||
| 1228 : | |||
| 1229 : | Arrays or lists are often simulated in shell by sandwiching the | ||
| 1230 : | colon `:' symbol between items | ||
| 1231 : | PATH=/bin:/usr/bin:/etc:/local/bin:. | ||
| 1232 : | |||
| 1233 : | LD_LIBARAY_PATH=/usr/lib:/usr/openwin/lib:/local/lib | ||
| 1234 : | |||
| 1235 : | but there is no real facility for arrays in the Bourne shell. Note that | ||
| 1236 : | the UNIX `cut' command can be used to extract the elements of the list. | ||
| 1237 : | Loops can also read such lists directly *Note Loops in sh::. A Perl | ||
| 1238 : | script can also be used. | ||
| 1239 : | |||
| 1240 : | The value of a variable is given by the dollar symbol as in C-shell. | ||
| 1241 : | It is also possible to use _curly braces_ around the variable name to | ||
| 1242 : | `protect' the variable from interfering text. For example: | ||
| 1243 : | $ animal=worm | ||
| 1244 : | $ echo book$animal | ||
| 1245 : | bookworm | ||
| 1246 : | $ thing=book | ||
| 1247 : | $ echo $thingworm | ||
| 1248 : | (nothing..) | ||
| 1249 : | $ echo ${thing}worm | ||
| 1250 : | bookworm | ||
| 1251 : | |||
| 1252 : | Default values can be given to variables in the Bourne shell. The | ||
| 1253 : | following commands illustrate this. | ||
| 1254 : | |||
| 1255 : | echo ${var-"No value set"} | ||
| 1256 : | echo ${var="Octopus"} | ||
| 1257 : | echo ${var+"Forced value"} | ||
| 1258 : | echo ${var?"No such variable"} | ||
| 1259 : | |||
| 1260 : | The first of these prints out the contents of `$var', if it is defined. | ||
| 1261 : | If it is not defined the variable is substituted for the string "No | ||
| 1262 : | value set". The value of `var' is not changed by this operation. It is | ||
| 1263 : | only for convenience. | ||
| 1264 : | |||
| 1265 : | The second command has the same effect as the first, but here the | ||
| 1266 : | value of `$var' is actually changed to "Octopus" if `$var' is not set. | ||
| 1267 : | |||
| 1268 : | The third version is slightly peculiar. If `$var' is _already_ set, | ||
| 1269 : | its value will be forced to be "Forced value", otherwise it is left | ||
| 1270 : | undefined. | ||
| 1271 : | |||
| 1272 : | Finally the last instance issues an error message "No such variable" | ||
| 1273 : | if `$var' is not defined. | ||
| 1274 : | |||
| 1275 : | |||
| 1276 : | File: unix.info, Node: stdin stdout stderr, Next: Arithmetic in sh, Prev: Variables and export, Up: Bourne shell | ||
| 1277 : | |||
| 1278 : | Stdin, stdout and stderr | ||
| 1279 : | ======================== | ||
| 1280 : | |||
| 1281 : | In the Bourne shell, the standard input/output files are referred to | ||
| 1282 : | by numbers rather than by names. | ||
| 1283 : | |||
| 1284 : | _stdin_ | ||
| 1285 : | File number 0 | ||
| 1286 : | |||
| 1287 : | _stdout_ | ||
| 1288 : | File number 1 | ||
| 1289 : | |||
| 1290 : | _stderr_ | ||
| 1291 : | File number 2 | ||
| 1292 : | |||
| 1293 : | The default routes for these files can be changed by _redirection_. | ||
| 1294 : | The redirection commands are more complicated than in C-shell, but they | ||
| 1295 : | are also more flexible. Here is a comparison. | ||
| 1296 : | |||
| 1297 : | sh csh Description | ||
| 1298 : | |||
| 1299 : | command > file command > file Stdout to file | ||
| 1300 : | command 1> file command > file Stdout to file | ||
| 1301 : | command 2> errs (No analogue) Stderr only to file errs | ||
| 1302 : | command 1> file 2>&1 command >& file stdout and stderr to file | ||
| 1303 : | command 1> file 2> errs (No analogue) stdout to file, stderr to errs | ||
| 1304 : | |||
| 1305 : | |||
| 1306 : | File: unix.info, Node: Arithmetic in sh, Next: Scripts and arguments, Prev: stdin stdout stderr, Up: Bourne shell | ||
| 1307 : | |||
| 1308 : | Arithmetic in sh | ||
| 1309 : | ================ | ||
| 1310 : | |||
| 1311 : | Arithmetic is performed entirely `by proxy'. There are no internal | ||
| 1312 : | arithmetic operators as in the C-shell. To evaluate an expression we | ||
| 1313 : | call the `expr' command or the `bc' precision calculator. Here are some | ||
| 1314 : | examples of `expr' | ||
| 1315 : | a=`expr $a+1` # increment a | ||
| 1316 : | a=`expr 4 + 10 \* 5` # 4+10*5 | ||
| 1317 : | check = `expr $a \> $b` # true=1, false=0. True if $a > $b | ||
| 1318 : | |||
| 1319 : | `expr' is very sensitive to spaces and backslash characters. | ||
| 1320 : | |||
| 1321 : | |||
| 1322 : | File: unix.info, Node: Scripts and arguments, Next: Return codes, Prev: Arithmetic in sh, Up: Bourne shell | ||
| 1323 : | |||
| 1324 : | Scripts and arguments | ||
| 1325 : | ===================== | ||
| 1326 : | |||
| 1327 : | Scripts are created by making an executable file which begins with | ||
| 1328 : | the sequence of characters | ||
| 1329 : | |||
| 1330 : | #!/bin/sh | ||
| 1331 : | |||
| 1332 : | Although we didn't discuss it before, this construction is quite | ||
| 1333 : | general: any executable file which begins with a sequence | ||
| 1334 : | #!myprogram -option | ||
| 1335 : | |||
| 1336 : | will cause the shell to attempt to execute | ||
| 1337 : | myprogam -option filename | ||
| 1338 : | |||
| 1339 : | where FILENAME is the name of the file. | ||
| 1340 : | |||
| 1341 : | If a script is to accept arguments then these can be referred to as | ||
| 1342 : | ` $1 $2 $3..$9'. There is a logical limit of nine arguments to a | ||
| 1343 : | script, but in practice it is possibile to get around this limitation. | ||
| 1344 : | `$0' is the name of the script itself. | ||
| 1345 : | |||
| 1346 : | Here is a simple script in the Bourne shell which prints out all its | ||
| 1347 : | arguments. | ||
| 1348 : | |||
| 1349 : | #!/bin/sh | ||
| 1350 : | # | ||
| 1351 : | # Print all arguments (version 1) | ||
| 1352 : | # | ||
| 1353 : | |||
| 1354 : | for arg in $* | ||
| 1355 : | do | ||
| 1356 : | echo Argument $arg | ||
| 1357 : | done | ||
| 1358 : | |||
| 1359 : | echo Total number of arguments was $# | ||
| 1360 : | |||
| 1361 : | The `$*' symbol stands for the entire list of arguments (like `$argv' | ||
| 1362 : | in C-shell) and `$#' is the total number of arguments (like `$#argv' in | ||
| 1363 : | C-shell). | ||
| 1364 : | |||
| 1365 : | Another way of achieving the same is to use the `shift' command. We | ||
| 1366 : | shall meet this again in the Perl programming language. `shift' takes | ||
| 1367 : | the first argument from the argument list and deletes it, moving all of | ||
| 1368 : | the other arguments down one number - this is how we can handle long | ||
| 1369 : | lists of arguments in `sh'. | ||
| 1370 : | |||
| 1371 : | #!/bin/sh | ||
| 1372 : | # | ||
| 1373 : | # Print all arguments (version 2) | ||
| 1374 : | # | ||
| 1375 : | |||
| 1376 : | while ( true ) | ||
| 1377 : | do | ||
| 1378 : | arg=$1; | ||
| 1379 : | shift; | ||
| 1380 : | echo $arg was an argument; | ||
| 1381 : | if [ $# -eq 0 ]; then | ||
| 1382 : | break | ||
| 1383 : | fi | ||
| 1384 : | done | ||
| 1385 : | |||
| 1386 : | |||
| 1387 : | File: unix.info, Node: Return codes, Next: Tests in sh, Prev: Scripts and arguments, Up: Bourne shell | ||
| 1388 : | |||
| 1389 : | Return codes | ||
| 1390 : | ============ | ||
| 1391 : | |||
| 1392 : | All programs which execute in UNIX return a value through the C | ||
| 1393 : | `return' command. There is a convention that a return value of zero (0) | ||
| 1394 : | means that everything went well, whereas any other value implies that | ||
| 1395 : | some error occurred. The return value is usually the value returned in | ||
| 1396 : | `errno', the extenal error variable in C. | ||
| 1397 : | |||
| 1398 : | Shell scripts can test for these values either by placing the command | ||
| 1399 : | directly inside an `if' test, or by testing the variable `$?' which is | ||
| 1400 : | always set to the return code of the last command. Some examples are | ||
| 1401 : | given following the next two sections. | ||
| 1402 : | |||
| 1403 : | |||
| 1404 : | File: unix.info, Node: Tests in sh, Next: Input in sh, Prev: Return codes, Up: Bourne shell | ||
| 1405 : | |||
| 1406 : | Tests and conditionals | ||
| 1407 : | ====================== | ||
| 1408 : | |||
| 1409 : | The Bourne shell has the usual array of tests. They are written as | ||
| 1410 : | follows. Notice that `test' is itself not a part of the shell, but is a | ||
| 1411 : | program which works out conditions and provides a return code. See the | ||
| 1412 : | manual page on `test' for more details. | ||
| 1413 : | |||
| 1414 : | `test -f FILE' | ||
| 1415 : | True if the file is a plain file | ||
| 1416 : | |||
| 1417 : | `test -d FILE' | ||
| 1418 : | True if the file is a directory | ||
| 1419 : | |||
| 1420 : | `test -r FILE' | ||
| 1421 : | True if the file is readable | ||
| 1422 : | |||
| 1423 : | `test -w FILE' | ||
| 1424 : | True if the file is writable | ||
| 1425 : | |||
| 1426 : | `test -x FILE' | ||
| 1427 : | True if the file is executable | ||
| 1428 : | |||
| 1429 : | `test -s FILE' | ||
| 1430 : | True if the file contains something | ||
| 1431 : | |||
| 1432 : | `test -g FILE' | ||
| 1433 : | True if setgid bit is set | ||
| 1434 : | |||
| 1435 : | `test -u FILE' | ||
| 1436 : | True if setuid bit is set | ||
| 1437 : | |||
| 1438 : | `test s1 = s2' | ||
| 1439 : | True if strings s1 and s2 are equal | ||
| 1440 : | |||
| 1441 : | `test s1 != s2' | ||
| 1442 : | True if strings s1 and s2 are unequal | ||
| 1443 : | |||
| 1444 : | `test X -eq Y' | ||
| 1445 : | True if the integers X and Y are numerically equal | ||
| 1446 : | |||
| 1447 : | `test X -ne Y' | ||
| 1448 : | True if integers are not equal | ||
| 1449 : | |||
| 1450 : | `test X -gt Y' | ||
| 1451 : | True if X is greater than Y | ||
| 1452 : | |||
| 1453 : | `test X -lt Y' | ||
| 1454 : | True if X is less than Y | ||
| 1455 : | |||
| 1456 : | `test X -ge Y' | ||
| 1457 : | True if X>=Y | ||
| 1458 : | |||
| 1459 : | `test X -le Y' | ||
| 1460 : | True if X <= Y | ||
| 1461 : | |||
| 1462 : | `!' | ||
| 1463 : | Logical NOT operator | ||
| 1464 : | |||
| 1465 : | `-a' | ||
| 1466 : | Logical AND | ||
| 1467 : | |||
| 1468 : | `-o' | ||
| 1469 : | Logical OR | ||
| 1470 : | |||
| 1471 : | Note that an alternate syntax for writing these commands if to use | ||
| 1472 : | the square brackets, instead of writing the word test. | ||
| 1473 : | [ $x -lt $y ] "==" test $x -lt $y | ||
| 1474 : | |||
| 1475 : | The conditional structures have the following syntax. | ||
| 1476 : | if UNIX-COMMAND | ||
| 1477 : | then | ||
| 1478 : | COMMAND | ||
| 1479 : | else | ||
| 1480 : | COMMANDS | ||
| 1481 : | fi | ||
| 1482 : | |||
| 1483 : | The `else' clause is, of course, optional. As noted before, the first | ||
| 1484 : | unix command could be _anything_, since every command has a return | ||
| 1485 : | code. The result is TRUE if it evaluates to _zero_ and false otherwise | ||
| 1486 : | (in contrast to the conventions in most languages). Multiple tests can | ||
| 1487 : | be made using | ||
| 1488 : | if UNIX-COMMAND | ||
| 1489 : | then | ||
| 1490 : | COMMANDS | ||
| 1491 : | elif UNIX-COMMAND | ||
| 1492 : | then | ||
| 1493 : | COMMANDS | ||
| 1494 : | elif UNIX-COMMAND | ||
| 1495 : | then | ||
| 1496 : | COMMANDS | ||
| 1497 : | else | ||
| 1498 : | COMMANDS | ||
| 1499 : | fi | ||
| 1500 : | |||
| 1501 : | where `elif' means `else-if'. | ||
| 1502 : | |||
| 1503 : | The equivalent of the C-school's `switch' statement is a more | ||
| 1504 : | Pascal-like `case' structure. | ||
| 1505 : | case UNIX-COMMAND-OR-VARIABLE in | ||
| 1506 : | |||
| 1507 : | wildcard1) COMMANDS ;; | ||
| 1508 : | wildcard2) COMMANDS ;; | ||
| 1509 : | wildcard3) COMMANDS ;; | ||
| 1510 : | |||
| 1511 : | esac | ||
| 1512 : | |||
| 1513 : | This structure uses the wildcards to match the output of the command or | ||
| 1514 : | variable in the first line. The first pattern which matches gets | ||
| 1515 : | executed. | ||
| 1516 : |
| Administrator | ViewVC Help |
| Powered by ViewVC 1.0.3 |