|
|
1.1 ! root 1: .\" Copyright (c) 1980 Regents of the University of California. ! 2: .\" All rights reserved. The Berkeley software License Agreement ! 3: .\" specifies the terms and conditions for redistribution. ! 4: .\" ! 5: .\" @(#)csh.3 6.1 (Berkeley) 5/23/86 ! 6: .\" ! 7: .nr H1 2 ! 8: .NH ! 9: Shell control structures and command scripts ! 10: .NH 2 ! 11: Introduction ! 12: .PP ! 13: It is possible to place commands in files and to cause shells to be ! 14: invoked to read and execute commands from these files, ! 15: which are called ! 16: .I "shell scripts." ! 17: We here detail those features of the shell useful to the writers of such ! 18: scripts. ! 19: .NH 2 ! 20: Make ! 21: .PP ! 22: It is important to first note what shell scripts are ! 23: .I not ! 24: useful for. ! 25: There is a program called ! 26: .I make ! 27: which is very useful for maintaining a group of related files ! 28: or performing sets of operations on related files. ! 29: For instance a large program consisting of one or more files ! 30: can have its dependencies described in a ! 31: .I makefile ! 32: which contains definitions of the commands used to create these ! 33: different files when changes occur. ! 34: Definitions of the means for printing listings, cleaning up the directory ! 35: in which the files reside, and installing the resultant programs ! 36: are easily, and most appropriately placed in this ! 37: .I makefile. ! 38: This format is superior and preferable to maintaining a group of shell ! 39: procedures to maintain these files. ! 40: .PP ! 41: Similarly when working on a document a ! 42: .I makefile ! 43: may be created which defines how different versions of the document ! 44: are to be created and which options of ! 45: .I nroff ! 46: or ! 47: .I troff ! 48: are appropriate. ! 49: .NH 2 ! 50: Invocation and the argv variable ! 51: .PP ! 52: A ! 53: .I csh ! 54: command script may be interpreted by saying ! 55: .DS ! 56: % csh script ... ! 57: .DE ! 58: where ! 59: .I script ! 60: is the name of the file containing a group of ! 61: .I csh ! 62: commands and ! 63: `\&...' is replaced by a sequence of arguments. ! 64: The shell places these arguments in the variable ! 65: .I argv ! 66: and then begins to read commands from the script. ! 67: These parameters are then available through the same mechanisms ! 68: which are used to reference any other shell variables. ! 69: .PP ! 70: If you make the file ! 71: `script' ! 72: executable by doing ! 73: .DS ! 74: chmod 755 script ! 75: .DE ! 76: and place a shell comment at the beginning of the shell script ! 77: (i.e. begin the file with a `#' character) ! 78: then a `/bin/csh' will automatically be invoked to execute `script' when ! 79: you type ! 80: .DS ! 81: script ! 82: .DE ! 83: If the file does not begin with a `#' then the standard shell ! 84: `/bin/sh' will be used to execute it. ! 85: This allows you to convert your older shell scripts to use ! 86: .I csh ! 87: at your convenience. ! 88: .NH 2 ! 89: Variable substitution ! 90: .PP ! 91: After each input line is broken into words and history substitutions ! 92: are done on it, the input line is parsed into distinct commands. ! 93: Before each command is executed a mechanism know as ! 94: .I "variable substitution" ! 95: is done on these words. ! 96: Keyed by the character `$' this substitution replaces the names ! 97: of variables by their values. ! 98: Thus ! 99: .DS ! 100: echo $argv ! 101: .DE ! 102: when placed in a command script would cause the current value of the ! 103: variable ! 104: .I argv ! 105: to be echoed to the output of the shell script. ! 106: It is an error for ! 107: .I argv ! 108: to be unset at this point. ! 109: .PP ! 110: A number of notations are provided for accessing components and attributes ! 111: of variables. ! 112: The notation ! 113: .DS ! 114: $?name ! 115: .DE ! 116: expands to `1' if name is ! 117: .I set ! 118: or to `0' ! 119: if name is not ! 120: .I set. ! 121: It is the fundamental mechanism used for checking whether particular ! 122: variables have been assigned values. ! 123: All other forms of reference to undefined variables cause errors. ! 124: .PP ! 125: The notation ! 126: .DS ! 127: $#name ! 128: .DE ! 129: expands to the number of elements in the variable ! 130: .I name. ! 131: Thus ! 132: .DS ! 133: % set argv=(a b c) ! 134: % echo $?argv ! 135: 1 ! 136: % echo $#argv ! 137: 3 ! 138: % unset argv ! 139: % echo $?argv ! 140: 0 ! 141: % echo $argv ! 142: Undefined variable: argv. ! 143: % ! 144: .DE ! 145: .PP ! 146: It is also possible to access the components of a variable ! 147: which has several values. ! 148: Thus ! 149: .DS ! 150: $argv[1] ! 151: .DE ! 152: gives the first component of ! 153: .I argv ! 154: or in the example above `a'. ! 155: Similarly ! 156: .DS ! 157: $argv[$#argv] ! 158: .DE ! 159: would give `c', ! 160: and ! 161: .DS ! 162: $argv[1\-2] ! 163: .DE ! 164: would give `a b'. Other notations useful in shell scripts are ! 165: .DS ! 166: $\fIn\fR ! 167: .DE ! 168: where ! 169: .I n ! 170: is an integer as a shorthand for ! 171: .DS ! 172: $argv[\fIn\fR\|] ! 173: .DE ! 174: the ! 175: .I n\|th ! 176: parameter and ! 177: .DS ! 178: $* ! 179: .DE ! 180: which is a shorthand for ! 181: .DS ! 182: $argv ! 183: .DE ! 184: The form ! 185: .DS ! 186: $$ ! 187: .DE ! 188: expands to the process number of the current shell. ! 189: Since this process number is unique in the system it can ! 190: be used in generation of unique temporary file names. ! 191: The form ! 192: .DS ! 193: $< ! 194: .DE ! 195: is quite special and is replaced by the next line of input read from ! 196: the shell's standard input (not the script it is reading). This is ! 197: useful for writing shell scripts that are interactive, reading ! 198: commands from the terminal, or even writing a shell script that ! 199: acts as a filter, reading lines from its input file. Thus the sequence ! 200: .DS ! 201: echo 'yes or no?\ec' ! 202: set a=($<) ! 203: .DE ! 204: would write out the prompt `yes or no?' without a newline and then ! 205: read the answer into the variable `a'. In this case `$#a' would be ! 206: `0' if either a blank line or end-of-file (^D) was typed. ! 207: .PP ! 208: One minor difference between `$\fIn\fR\|' and `$argv[\fIn\fR\|]' ! 209: should be noted here. ! 210: The form ! 211: `$argv[\fIn\fR\|]' ! 212: will yield an error if ! 213: .I n ! 214: is not in the range ! 215: `1\-$#argv' ! 216: while `$n' ! 217: will never yield an out of range subscript error. ! 218: This is for compatibility with the way older shells handled parameters. ! 219: .PP ! 220: Another important point is that it is never an error to give a subrange ! 221: of the form `n\-'; if there are less than ! 222: .I n ! 223: components of the given variable then no words are substituted. ! 224: A range of the form `m\-n' likewise returns an empty vector without giving ! 225: an error when \fIm\fR exceeds the number of elements of the given variable, ! 226: provided the subscript \fIn\fR is in range. ! 227: .NH 2 ! 228: Expressions ! 229: .PP ! 230: In order for interesting shell scripts to be constructed it ! 231: must be possible to evaluate expressions in the shell based on the ! 232: values of variables. ! 233: In fact, all the arithmetic operations of the language C are available ! 234: in the shell ! 235: with the same precedence that they have in C. ! 236: In particular, the operations `==' and `!=' compare strings ! 237: and the operators `&&' and `|\|\||' implement the boolean and/or operations. ! 238: The special operators `=~' and `!~' are similar to `==' and `!=' except ! 239: that the string on the right side can have pattern matching characters ! 240: (like *, ? or []) and the test is whether the string on the left matches ! 241: the pattern on the right. ! 242: .PP ! 243: The shell also allows file enquiries of the form ! 244: .DS ! 245: \-? filename ! 246: .DE ! 247: where `?' is replace by a number of single characters. ! 248: For instance the expression primitive ! 249: .DS ! 250: \-e filename ! 251: .DE ! 252: tell whether the file ! 253: `filename' ! 254: exists. ! 255: Other primitives test for read, write and execute access to the file, ! 256: whether it is a directory, or has non-zero length. ! 257: .PP ! 258: It is possible to test whether a command terminates normally, ! 259: by a primitive of the ! 260: form `{ command }' which returns true, i.e. `1' if the command ! 261: succeeds exiting normally with exit status 0, or `0' if the command ! 262: terminates abnormally or with exit status non-zero. ! 263: If more detailed information about the execution status of a command ! 264: is required, it can be executed and the variable `$status' examined ! 265: in the next command. ! 266: Since `$status' is set by every command, it is very transient. ! 267: It can be saved if it is inconvenient to use it only in the single ! 268: immediately following command. ! 269: .PP ! 270: For a full list of expression components available see the manual ! 271: section for the shell. ! 272: .NH 2 ! 273: Sample shell script ! 274: .PP ! 275: A sample shell script which makes use of the expression mechanism ! 276: of the shell and some of its control structure follows: ! 277: .DS ! 278: % cat copyc ! 279: # ! 280: # Copyc copies those C programs in the specified list ! 281: # to the directory ~/backup if they differ from the files ! 282: # already in ~/backup ! 283: # ! 284: set noglob ! 285: foreach i ($argv) ! 286: ! 287: if ($i !~ *.c) continue # not a .c file so do nothing ! 288: ! 289: if (! \-r ~/backup/$i:t) then ! 290: echo $i:t not in backup... not cp\e\'ed ! 291: continue ! 292: endif ! 293: ! 294: cmp \-s $i ~/backup/$i:t # to set $status ! 295: ! 296: if ($status != 0) then ! 297: echo new backup of $i ! 298: cp $i ~/backup/$i:t ! 299: endif ! 300: end ! 301: .DE ! 302: .PP ! 303: This script makes use of the ! 304: .I foreach ! 305: command, which causes the shell to execute the commands between the ! 306: .I foreach ! 307: and the matching ! 308: .I end ! 309: for each of the values given between `(' and `)' with the named ! 310: variable, in this case `i' set to successive values in the list. ! 311: Within this loop we may use the command ! 312: .I break ! 313: to stop executing the loop ! 314: and ! 315: .I continue ! 316: to prematurely terminate one iteration ! 317: and begin the next. ! 318: After the ! 319: .I foreach ! 320: loop the iteration variable ! 321: (\fIi\fR in this case) ! 322: has the value at the last iteration. ! 323: .PP ! 324: We set the variable ! 325: .I noglob ! 326: here to prevent filename expansion of the members of ! 327: .I argv. ! 328: This is a good idea, in general, if the arguments to a shell script ! 329: are filenames which have already been expanded or if the arguments ! 330: may contain filename expansion metacharacters. ! 331: It is also possible to quote each use of a `$' variable expansion, ! 332: but this is harder and less reliable. ! 333: .PP ! 334: The other control construct used here is a statement of the form ! 335: .DS ! 336: \fBif\fR ( expression ) \fBthen\fR ! 337: command ! 338: ... ! 339: \fBendif\fR ! 340: .DE ! 341: The placement of the keywords here is ! 342: .B not ! 343: flexible due to the current implementation of the shell.\(dg ! 344: .FS ! 345: \(dgThe following two formats are not currently acceptable to the shell: ! 346: .sp ! 347: .in +5 ! 348: .nf ! 349: \fBif\fR ( expression ) # \fBWon't work!\fR ! 350: \fBthen\fR ! 351: command ! 352: ... ! 353: \fBendif\fR ! 354: .fi ! 355: .in -5 ! 356: .sp ! 357: and ! 358: .sp ! 359: .in +5 ! 360: .nf ! 361: \fBif\fR ( expression ) \fBthen\fR command \fBendif\fR # \fBWon't work\fR ! 362: .in -5 ! 363: .fi ! 364: .FE ! 365: .PP ! 366: The shell does have another form of the if statement of the form ! 367: .DS ! 368: \fBif\fR ( expression ) \fBcommand\fR ! 369: .DE ! 370: which can be written ! 371: .DS ! 372: \fBif\fR ( expression ) \e ! 373: command ! 374: .DE ! 375: Here we have escaped the newline for the sake of appearance. ! 376: The command must not involve `\||\|', `&' or `;' ! 377: and must not be another control command. ! 378: The second form requires the final `\e' to ! 379: .B immediately ! 380: precede the end-of-line. ! 381: .PP ! 382: The more general ! 383: .I if ! 384: statements above also admit a sequence of ! 385: .I else\-if ! 386: pairs followed by a single ! 387: .I else ! 388: and an ! 389: .I endif, ! 390: e.g.: ! 391: .DS ! 392: \fBif\fR ( expression ) \fBthen\fR ! 393: commands ! 394: \fBelse\fR \fBif\fR (expression ) \fBthen\fR ! 395: commands ! 396: \&... ! 397: ! 398: \fBelse\fR ! 399: commands ! 400: \fBendif\fR ! 401: .DE ! 402: .PP ! 403: Another important mechanism used in shell scripts is the `:' modifier. ! 404: We can use the modifier `:r' here to extract a root of a filename or ! 405: `:e' to extract the ! 406: .I extension. ! 407: Thus if the variable ! 408: .I i ! 409: has the value ! 410: `/mnt/foo.bar' ! 411: then ! 412: .sp ! 413: .in +5 ! 414: .nf ! 415: % echo $i $i:r $i:e ! 416: /mnt/foo.bar /mnt/foo bar ! 417: % ! 418: .sp ! 419: .in -5 ! 420: .fi ! 421: shows how the `:r' modifier strips off the trailing `.bar' and the ! 422: the `:e' modifier leaves only the `bar'. ! 423: Other modifiers will take off the last component of a pathname leaving ! 424: the head `:h' or all but the last component of a pathname leaving the ! 425: tail `:t'. ! 426: These modifiers are fully described in the ! 427: .I csh ! 428: manual pages in the User's Reference Manual. ! 429: It is also possible to use the ! 430: .I "command substitution" ! 431: mechanism described in the next major section to perform modifications ! 432: on strings to then reenter the shell's environment. ! 433: Since each usage of this mechanism involves the creation of a new process, ! 434: it is much more expensive to use than the `:' modification mechanism.\(dd ! 435: .FS ! 436: \(dd It is also important to note that ! 437: the current implementation of the shell limits the number of `:' modifiers ! 438: on a `$' substitution to 1. ! 439: Thus ! 440: .sp ! 441: .nf ! 442: .in +5 ! 443: % echo $i $i:h:t ! 444: /a/b/c /a/b:t ! 445: % ! 446: .in -5 ! 447: .fi ! 448: .sp ! 449: does not do what one would expect. ! 450: .FE ! 451: Finally, we note that the character `#' lexically introduces a shell ! 452: comment in shell scripts (but not from the terminal). ! 453: All subsequent characters on the input line after a `#' are discarded ! 454: by the shell. ! 455: This character can be quoted using `\'' or `\e' to place it in ! 456: an argument word. ! 457: .NH 2 ! 458: Other control structures ! 459: .PP ! 460: The shell also has control structures ! 461: .I while ! 462: and ! 463: .I switch ! 464: similar to those of C. ! 465: These take the forms ! 466: .DS ! 467: \fBwhile\fR ( expression ) ! 468: commands ! 469: \fBend\fR ! 470: .DE ! 471: and ! 472: .DS ! 473: \fBswitch\fR ( word ) ! 474: ! 475: \fBcase\fR str1: ! 476: commands ! 477: \fBbreaksw\fR ! 478: ! 479: \& ... ! 480: ! 481: \fBcase\fR strn: ! 482: commands ! 483: \fBbreaksw\fR ! 484: ! 485: \fBdefault:\fR ! 486: commands ! 487: \fBbreaksw\fR ! 488: ! 489: \fBendsw\fR ! 490: .DE ! 491: For details see the manual section for ! 492: .I csh. ! 493: C programmers should note that we use ! 494: .I breaksw ! 495: to exit from a ! 496: .I switch ! 497: while ! 498: .I break ! 499: exits a ! 500: .I while ! 501: or ! 502: .I foreach ! 503: loop. ! 504: A common mistake to make in ! 505: .I csh ! 506: scripts is to use ! 507: .I break ! 508: rather than ! 509: .I breaksw ! 510: in switches. ! 511: .PP ! 512: Finally, ! 513: .I csh ! 514: allows a ! 515: .I goto ! 516: statement, with labels looking like they do in C, i.e.: ! 517: .DS ! 518: loop: ! 519: commands ! 520: \fBgoto\fR loop ! 521: .DE ! 522: .NH 2 ! 523: Supplying input to commands ! 524: .PP ! 525: Commands run from shell scripts receive by default the standard ! 526: input of the shell which is running the script. ! 527: This is different from previous shells running ! 528: under \s-2UNIX\s0. It allows shell scripts to fully participate ! 529: in pipelines, but mandates extra notation for commands which are to take ! 530: inline data. ! 531: .PP ! 532: Thus we need a metanotation for supplying inline data to commands in ! 533: shell scripts. ! 534: As an example, consider this script which runs the editor to ! 535: delete leading blanks from the lines in each argument file: ! 536: .DS ! 537: % cat deblank ! 538: # deblank \-\- remove leading blanks ! 539: foreach i ($argv) ! 540: ed \- $i << \'EOF\' ! 541: 1,$s/^[ ]*// ! 542: w ! 543: q ! 544: \&\'EOF\' ! 545: end ! 546: % ! 547: .DE ! 548: The notation `<< \'EOF\'' ! 549: means that the standard input for the ! 550: .I ed ! 551: command is to come from the text in the shell script file ! 552: up to the next line consisting of exactly `\'EOF\''. ! 553: The fact that the `EOF' is enclosed in `\'' characters, i.e. quoted, ! 554: causes the shell to not perform variable substitution on the ! 555: intervening lines. ! 556: In general, if any part of the word following the `<<' which the ! 557: shell uses to terminate the text to be given to the command is quoted ! 558: then these substitutions will not be performed. ! 559: In this case since we used the form `1,$' in our editor script ! 560: we needed to insure that this `$' was not variable substituted. ! 561: We could also have insured this by preceding the `$' here with a `\e', ! 562: i.e.: ! 563: .DS ! 564: 1,\e$s/^[ ]*// ! 565: .DE ! 566: but quoting the `EOF' terminator is a more reliable way of achieving the ! 567: same thing. ! 568: .NH 2 ! 569: Catching interrupts ! 570: .PP ! 571: If our shell script creates temporary files, we may wish to catch ! 572: interruptions of the shell script so that we can clean up ! 573: these files. ! 574: We can then do ! 575: .DS ! 576: onintr label ! 577: .DE ! 578: where ! 579: .I label ! 580: is a label in our program. ! 581: If an interrupt is received the shell will do a ! 582: `goto label' ! 583: and we can remove the temporary files and then do an ! 584: .I exit ! 585: command (which is built in to the shell) ! 586: to exit from the shell script. ! 587: If we wish to exit with a non-zero status we can do ! 588: .DS ! 589: exit(1) ! 590: .DE ! 591: e.g. to exit with status `1'. ! 592: .NH 2 ! 593: What else? ! 594: .PP ! 595: There are other features of the shell useful to writers of shell ! 596: procedures. ! 597: The ! 598: .I verbose ! 599: and ! 600: .I echo ! 601: options and the related ! 602: .I \-v ! 603: and ! 604: .I \-x ! 605: command line options can be used to help trace the actions of the shell. ! 606: The ! 607: .I \-n ! 608: option causes the shell only to read commands and not to execute ! 609: them and may sometimes be of use. ! 610: .PP ! 611: One other thing to note is that ! 612: .I csh ! 613: will not execute shell scripts which do not begin with the ! 614: character `#', that is shell scripts that do not begin with a comment. ! 615: Similarly, the `/bin/sh' on your system may well defer to `csh' ! 616: to interpret shell scripts which begin with `#'. ! 617: This allows shell scripts for both shells to live in harmony. ! 618: .PP ! 619: There is also another quotation mechanism using `"' which allows ! 620: only some of the expansion mechanisms we have so far discussed to occur ! 621: on the quoted string and serves to make this string into a single word ! 622: as `\'' does. ! 623: .bp
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.