# To unbundle, run this file echo t.mac sed 's/.//' >t.mac <<'//GO.SYSIN DD t.mac' -.ds ZZ \fB.\|.\|.\fP -.ds ST \v'.3m'\s+2*\s0\v'-.3m' -.ds DO \h'\w'do 'u' -.ds Ca \h'\w'case 'u' -.ds WH \h'\w'while 'u' -.ds VT \|\fB\(or\fP\| -.ds TH \h'\w'then 'u' -.ds DC \*(DO\*(CA -.ds AP >\h'-.2m'> -.ds HE <\h'-.2m'< -.. \" macros for algol 68c reference manual -.ds DA 1977 November 1 -.ds md \v'.25m' -.ds mu \v'-.25m' -.ds U \*(mu\s-3 -.ds V \s0\*(md -.ds L \*(md\s-3 -.ds M \s0\*(mu -.ds S \s-1 -.ds T \s0 -.. \" small 1 -.ds O \*S1\*T -.ds h \| -.ds s \|\| -.. \" ellipsis -.ds e .\|.\|. -.. \" subscripts -.ds 1 \*(md\s-41\s0\*(mu -.ds 2 \*(md\s-42\s0\*(mu //GO.SYSIN DD t.mac echo t1 sed 's/.//' >t1 <<'//GO.SYSIN DD t1' -.RP -.TL -An Introduction to the UNIX Shell -.AU -S. R. Bourne -.AI -.MH -.AB -.LP -The -.ul -shell -is a command programming language that provides an interface -to the -.UX -operating system. -Its features include -control-flow primitives, parameter passing, variables and -string substitution. -Constructs such as -.ul -while, if then else, case -and -.ul -for -are available. -Two-way communication is possible between the -.ul -shell -and commands. -String-valued parameters, typically file names or flags, may be -passed to a command. -A return code is set by commands that may be used to determine control-flow, -and the standard output from a command may be used -as shell input. -.LP -The -.ul -shell -can modify the environment -in which commands run. -Input and output can be redirected -to files, and processes that communicate through `pipes' -can be invoked. -Commands are found by -searching directories -in the file system in a -sequence that can be defined by the user. -Commands can be read either from the terminal or from a file, -which allows command procedures to be -stored for later use. -.AE -.ds ST \v'.3m'\s+2*\s0\v'-.3m' -.SH -1.0\ Introduction -.LP -The shell is both a command language -and a programming language -that provides an interface to the UNIX -operating system. -This memorandum describes, with -examples, the UNIX shell. -The first section covers most of the -everyday requirements -of terminal users. -Some familiarity with UNIX -is an advantage when reading this section; -see, for example, -"UNIX for beginners". -.[ -unix beginn kernigh 1978 -.] -Section 2 describes those features -of the shell primarily intended -for use within shell procedures. -These include the control-flow -primitives and string-valued variables -provided by the shell. -A knowledge of a programming language -would be a help when reading this section. -The last section describes the more -advanced features of the shell. -References of the form "see \fIpipe\fP (2)" -are to a section of the UNIX manual. -.[ -seventh 1978 ritchie thompson -.] -.SH -1.1\ Simple\ commands -.LP -Simple commands consist of one or more words -separated by blanks. -The first word is the name of the command -to be executed; any remaining words -are passed as arguments to the command. -For example, -.DS - who -.DE -is a command that prints the names -of users logged in. -The command -.DS - ls \(mil -.DE -prints a list of files in the current -directory. -The argument \fI\(mil\fP tells \fIls\fP -to print status information, size and -the creation date for each file. -.SH -1.2\ Background\ commands -.LP -To execute a command the shell normally -creates a new \fIprocess\fP -and waits for it to finish. -A command may be run without waiting -for it to finish. -For example, -.DS - cc pgm.c & -.DE -calls the C compiler to compile -the file \fIpgm.c\|.\fP -The trailing \fB&\fP is an operator that instructs the shell -not to wait for the command to finish. -To help keep track of such a process -the shell reports its process -number following its creation. -A list of currently active processes may be obtained -using the \fIps\fP command. -.SH -1.3\ Input\ output\ redirection -.LP -Most commands produce output on the standard output -that is initially connected to the terminal. -This output may be sent to a file -by writing, for example, -.DS - ls \(mil >file -.DE -The notation \fI>file\fP -is interpreted by the shell and is not passed -as an argument to \fIls.\fP -If \fIfile\fP does not exist then the -shell creates it; -otherwise the original contents of -\fIfile\fP are replaced with the output -from \fIls.\fP -Output may be appended to a file -using the notation -.DS - ls \(mil \*(APfile -.DE -In this case \fIfile\fP is also created if it does not already -exist. -.LP -The standard input of a command may be taken -from a file instead of the terminal by -writing, for example, -.DS - wc file; wc \*(ST ? \*(VT &\|,\fR -are called metacharacters. -A complete list of metacharacters is given -in appendix B. -Any character preceded by a \fB\\\fR is \fIquoted\fP -and loses its special meaning, if any. -The \fB\\\fP is elided so that -.DS - echo \\\\? -.DE -will echo a single \fB?\|,\fP -and -.DS - echo \\\\\\\\ -.DE -will echo a single \fB\\\|.\fR -To allow long strings to be continued over -more than one line -the sequence \fB\\newline\fP -is ignored. -.LP -\fB\\\fP is convenient for quoting -single characters. -When more than one character needs -quoting the above mechanism is clumsy and -error prone. -A string of characters may be quoted -by enclosing the string between single quotes. -For example, -.DS - echo xx\'\*(ST\*(ST\*(ST\*(ST\'xx -.DE -will echo -.DS - xx\*(ST\*(ST\*(ST\*(STxx -.DE -The quoted string may not contain -a single quote -but may contain newlines, which are preserved. -This quoting mechanism is the most -simple and is recommended -for casual use. -.LP -A third quoting mechanism using double quotes -is also available -that prevents interpretation of some but not all -metacharacters. -Discussion of the -details is deferred -to section 3.4\|. -.SH -1.7\ Prompting -.LP -When the shell is used from a terminal it will -issue a prompt before reading a command. -By default this prompt is `\fB$\ \fR'\|. -It may be changed by saying, -for example, -.DS - \s-1PS1\s0=yesdear -.DE -that sets the prompt to be the string \fIyesdear\|.\fP -If a newline is typed and further input is needed -then the shell will issue the prompt `\fB>\ \fR'\|. -Sometimes this can be caused by mistyping -a quote mark. -If it is unexpected then an interrupt (\s-1DEL\s0) -will return the shell to read another command. -This prompt may be changed by saying, for example, -.DS - \s-1PS2\s0=more -.DE -.SH -1.8\ The\ shell\ and\ login -.LP -Following \fIlogin\fP (1) -the shell is called to read and execute -commands typed at the terminal. -If the user's login directory -contains the file \fB.profile\fP -then it is assumed to contain commands -and is read by the shell before reading -any commands from the terminal. -.SH -1.9\ Summary -.sp -.RS -.IP \(bu -\fBls\fP -.br -Print the names of files in the current directory. -.IP \(bu -\fBls >file\fP -.br -Put the output from \fIls\fP into \fIfile.\fP -.IP \(bu -\fBls \*(VT wc \(mil\fR -.br -Print the number of files in the current directory. -.IP \(bu -\fBls \*(VT grep old\fR -.br -Print those file names containing the string \fIold.\fP -.IP \(bu -\fBls \*(VT grep old \*(VT wc \(mil\fR -.br -Print the number of files whose name contains the string \fIold.\fP -.IP \(bu -\fBcc pgm.c &\fR -.br -Run \fIcc\fP in the background. -.RE //GO.SYSIN DD t1 echo t2 sed 's/.//' >t2 <<'//GO.SYSIN DD t2' -.bp -.SH -2.0\ Shell\ procedures -.LP -The shell may be used to read and execute commands -contained in a file. -For example, -.DS - sh file [ args \*(ZZ ] -.DE -calls the shell to read commands from \fIfile.\fP -Such a file is called a \fIcommand procedure\fP -or \fIshell procedure.\fP -Arguments may be supplied with the call -and are referred to in \fIfile\fP -using the positional parameters -\fB$1, $2, \*(ZZ\|.\fR -For example, if the file \fIwg\fP contains -.DS - who \*(VT grep $1 -.DE -then -.DS - sh wg fred -.DE -is equivalent to -.DS - who \*(VT grep fred -.DE -.LP -UNIX files have three independent attributes, -\fIread,\fP \fIwrite\fP and \fIexecute.\fP -The UNIX command \fIchmod\fP (1) may be used -to make a file executable. -For example, -.DS - chmod +x wg -.DE -will ensure that the file \fIwg\fP has execute status. -Following this, the command -.DS - wg fred -.DE -is equivalent to -.DS - sh wg fred -.DE -This allows shell procedures and programs -to be used interchangeably. -In either case a new process is created to -run the command. -.LP -As well as providing names for the positional -parameters, -the number of positional parameters in the call -is available as \fB$#\|.\fP -The name of the file being executed -is available as \fB$0\|.\fP -.LP -A special shell parameter \fB$\*(ST\fP -is used to substitute for all positional parameters -except \fB$0\|.\fP -A typical use of this is to provide -some default arguments, -as in, -.DS - nroff \(miT450 \(mims $\*(ST -.DE -which simply prepends some arguments -to those already given. -.SH -2.1\ Control\ flow\ -\ for -.LP -A frequent use of shell procedures is to loop -through the arguments (\fB$1, $2, \*(ZZ\fR) -executing commands once for each argument. -An example of such a procedure is -\fItel\fP that searches the file -\fB/usr/lib/telnos\fR -that contains lines of the form -.DS - \*(ZZ - fred mh0123 - bert mh0789 - \*(ZZ -.DE -The text of \fItel\fP is -.DS - for i - do grep $i /usr/lib/telnos; done -.DE -The command -.DS - tel fred -.DE -prints those lines in \fB/usr/lib/telnos\fR -that contain the string \fIfred\|.\fP -.DS - tel fred bert -.DE -prints those lines containing \fIfred\fP -followed by those for \fIbert.\fP -.LP -The \fBfor\fP loop notation is recognized by the shell -and has the general form -.DS - \fBfor\fR \fIname\fR \fBin\fR \fIw1 w2 \*(ZZ\fR - \fBdo\fR \fIcommand-list\fR - \fBdone\fR -.DE -A \fIcommand-list\fP is a sequence of one or more -simple commands separated or terminated by a newline or semicolon. -Furthermore, reserved words -like \fBdo\fP and \fBdone\fP are only -recognized following a newline or -semicolon. -\fIname\fP is a shell variable that is set -to the words \fIw1 w2 \*(ZZ\fR in turn each time the \fIcommand-list\fP -following \fBdo\fP -is executed. -If \fBin\fR \fIw1 w2 \*(ZZ\fR -is omitted then the loop -is executed once for each positional parameter; -that is, \fBin\fR \fI$\*(ST\fR is assumed. -.LP -Another example of the use of the \fBfor\fP -loop is the \fIcreate\fP command -whose text is -.DS - for i do >$i; done -.DE -The command -.DS - create alpha beta -.DE -ensures that two empty files -\fIalpha\fP and \fIbeta\fP exist -and are empty. -The notation \fI>file\fP may be used on its -own to create or clear the contents of a file. -Notice also that a semicolon (or newline) is required before \fBdone.\fP -.SH -2.2\ Control\ flow\ -\ case -.LP -A multiple way branch is provided for by the -\fBcase\fP notation. -For example, -.DS - case $# in - \*(Ca1) cat \*(AP$1 ;; - \*(Ca2) cat \*(AP$2 <$1 ;; - \*(Ca\*(ST) echo \\'usage: append [ from ] to\\' ;; - esac -.DE -is an \fIappend\fP command. -When called -with one argument as -.DS - append file -.DE -\fB$#\fP is the string \fI1\fP and -the standard input is copied onto the -end of \fIfile\fP -using the \fIcat\fP command. -.DS - append file1 file2 -.DE -appends the contents of \fIfile1\fP -onto \fIfile2.\fP -If the number of arguments supplied to -\fIappend\fP is other than 1 or 2 -then a message is printed indicating -proper usage. -.LP -The general form of the \fBcase\fP command -is -.DS - \fBcase \fIword \fBin - \*(Ca\fIpattern\|\fB)\ \fIcommand-list\fB\|;; - \*(Ca\*(ZZ - \fBesac\fR -.DE -The shell attempts to match -\fIword\fR with each \fIpattern,\fR -in the order in which the patterns -appear. -If a match is found the -associated \fIcommand-list\fP is -executed and execution -of the \fBcase\fP is complete. -Since \*(ST is the pattern that matches any -string it can be used for the default case. -.LP -A word of caution: -no check is made to ensure that only -one pattern matches -the case argument. -The first match found defines the set of commands -to be executed. -In the example below the commands following -the second \*(ST will never be executed. -.DS - case $# in - \*(Ca\*(ST) \*(ZZ ;; - \*(Ca\*(ST) \*(ZZ ;; - esac -.DE -.LP -Another example of the use of the \fBcase\fP -construction is to distinguish -between different forms -of an argument. -The following example is a fragment of a \fIcc\fP command. -.DS - for i - do case $i in - \*(DC\(mi[ocs]) \*(ZZ ;; - \*(DC\(mi\*(ST) echo \\'unknown flag $i\\' ;; - \*(DC\*(ST.c) /lib/c0 $i \*(ZZ ;; - \*(DC\*(ST) echo \\'unexpected argument $i\\' ;; - \*(DOesac - done -.DE -.LP -To allow the same commands to be associated -with more than one pattern -the \fBcase\fP command provides -for alternative patterns -separated by a \*(VT\|. -For example, -.DS - case $i in - \*(Ca\(mix\*(VT\(miy) \*(ZZ - esac -.DE -is equivalent to -.DS - case $i in - \*(Ca\(mi[xy]) \*(ZZ - esac -.DE -.LP -The usual quoting conventions apply -so that -.DS - case $i in - \*(Ca\\\\?) \*(ZZ -.DE -will match the character \fB?\|.\fP -.SH -2.3\ Here\ documents -.LP -The shell procedure \fItel\fP -in section 2.1 uses the file \fB/usr/lib/telnos\fR -to supply the data -for \fIgrep.\fP -An alternative is to include this -data -within the shell procedure as a \fIhere\fP document, as in, -.DS - for i - do grep $i \*(HE! - \*(DO\*(ZZ - \*(DOfred mh0123 - \*(DObert mh0789 - \*(DO\*(ZZ - ! - done -.DE -In this example -the shell takes the lines between \fB\*(HE!\fR and \fB!\fR -as the standard input for \fIgrep.\fP -The string \fB!\fR is arbitrary, the document -being terminated by a line that consists -of the string following \*(HE\|. -.LP -Parameters are substituted in the document -before it is made available to \fIgrep\fP -as illustrated by the following procedure -called \fIedg\|.\fP -.DS - ed $3 \*(HE% - g/$1/s//$2/g - w - % -.DE -The call -.DS - edg string1 string2 file -.DE -is then equivalent to the command -.DS - ed file \*(HE% - g/string1/s//string2/g - w - % -.DE -and changes all occurrences of \fIstring1\fP -in \fIfile\fP to \fIstring2\|.\fP -Substitution can be prevented using \\ -to quote the special character \fB$\fP -as in -.DS - ed $3 \*(HE+ - 1,\\\\$s/$1/$2/g - w - + -.DE -(This version of \fIedg\fP is equivalent to -the first except that \fIed\fP will print -a \fB?\fR if there are no occurrences of -the string \fB$1\|.\fP) -Substitution within a \fIhere\fP document -may be prevented entirely by quoting -the terminating string, -for example, -.DS - grep $i \*(HE\\\\# - \*(ZZ - # -.DE -The document is presented -without modification to \fIgrep.\fP -If parameter substitution is not required -in a \fIhere\fP document this latter form -is more efficient. -.SH -2.4\ Shell\ variables -.LP -The shell -provides string-valued variables. -Variable names begin with a letter -and consist of letters, digits and -underscores. -Variables may be given values by writing, for example, -.DS - user=fred\ box=m000\ acct=mh0000 -.DE -which assigns values to the variables -\fBuser, box\fP and \fBacct.\fP -A variable may be set to the null string -by saying, for example, -.DS - null= -.DE -The value of a variable is substituted -by preceding its name with \fB$\|;\fP -for example, -.DS - echo $user -.DE -will echo \fIfred.\fP -.LP -Variables may be used interactively -to provide abbreviations for frequently -used strings. -For example, -.DS - b=/usr/fred/bin - mv pgm $b -.DE -will move the file \fIpgm\fP -from the current directory to the directory \fB/usr/fred/bin\|.\fR -A more general notation is available for parameter -(or variable) -substitution, as in, -.DS - echo ${user} -.DE -which is equivalent to -.DS - echo $user -.DE -and is used when the parameter name is -followed by a letter or digit. -For example, -.DS - tmp=/tmp/ps - ps a >${tmp}a -.DE -will direct the output of \fIps\fR -to the file \fB/tmp/psa,\fR -whereas, -.DS - ps a >$tmpa -.DE -would cause the value of the variable \fBtmpa\fP -to be substituted. -.LP -Except for \fB$?\fP the following -are set initially by the shell. -\fB$?\fP is set after executing each command. -.RS -.IP \fB$?\fP 8 -The exit status (return code) -of the last command executed -as a decimal string. -Most commands return a zero exit status -if they complete successfully, -otherwise a non-zero exit status is returned. -Testing the value of return codes is dealt with -later under \fBif\fP and \fBwhile\fP commands. -.IP \fB$#\fP 8 -The number of positional parameters -(in decimal). -Used, for example, in the \fIappend\fP command -to check the number of parameters. -.IP \fB$$\fP 8 -The process number of this shell (in decimal). -Since process numbers are unique among -all existing processes, this string is -frequently used to generate -unique -temporary file names. -For example, -.DS - ps a >/tmp/ps$$ - \*(ZZ - rm /tmp/ps$$ -.DE -.IP \fB$\|!\fP 8 -The process number of the last process -run in the background (in decimal). -.IP \fB$\(mi\fP 8 -The current shell flags, such as -\fB\(mix\fR and \fB\(miv\|.\fR -.RE -.LP -Some variables have a special meaning to the -shell and should be avoided for general -use. -.RS -.IP \fB$\s-1MAIL\s0\fP 8 -When used interactively -the shell looks at the file -specified by this variable -before it issues a prompt. -If the specified file has been modified -since it -was last looked at the shell -prints the message -\fIyou have mail\fP before prompting -for the next command. -This variable is typically set -in the file \fB.profile,\fP -in the user's login directory. -For example, -.DS - \s-1MAIL\s0=/usr/mail/fred -.DE -.IP \fB$\s-1HOME\s0\fP 8 -The default argument -for the \fIcd\fP command. -The current directory is used to resolve -file name references that do not begin with -a \fB/\|,\fR -and is changed using the \fIcd\fP command. -For example, -.DS - cd /usr/fred/bin -.DE -makes the current directory \fB/usr/fred/bin\|.\fR -.DS - cat wn -.DE -will print on the terminal the file \fIwn\fP -in this directory. -The command -\fIcd\fP with no argument -is equivalent to -.DS - cd $\s-1HOME\s0 -.DE -This variable is also typically set in the -the user's login profile. -.IP \fB$\s-1PATH\s0\fP 8 -A list of directories that contain commands (the \fIsearch path\fR\|). -Each time a command is executed by the shell -a list of directories is searched -for an executable file. -.ne 5 -If \fB$\s-1PATH\s0\fP is not set -then the current directory, -\fB/bin\fP, and \fB/usr/bin\fP are searched by default. -.ne 5 -Otherwise \fB$\s-1PATH\s0\fP consists of directory -names separated by \fB:\|.\fP -For example, -.DS - \s-1PATH\s0=\fB:\fP/usr/fred/bin\fB:\fP/bin\fB:\fP/usr/bin -.DE -specifies that the current directory -(the null string before the first \fB:\fP\|), -\fB/usr/fred/bin, /bin \fRand\fP /usr/bin\fR -are to be searched in that order. -In this way individual users -can have their own `private' commands -that are accessible independently -of the current directory. -If the command name contains a \fB/\fR then this directory search -is not used; a single attempt -is made to execute the command. -.IP \fB$\s-1PS1\s0\fP 8 -The primary shell prompt string, by default, `\fB$\ \fR'. -.IP \fB$\s-1PS2\s0\fP 8 -The shell prompt when further input is needed, -by default, `\fB>\ \fR'. -.IP \fB$\s-1IFS\s0\fP 8 -The set of characters used by \fIblank -interpretation\fR (see section 3.4). -.RE -.SH -2.5\ The\ test\ command -.LP -The \fItest\fP command, although not part of the shell, -is intended for use by shell programs. -For example, -.DS - test \(mif file -.DE -returns zero exit status if \fIfile\fP -exists and non-zero exit status otherwise. -In general \fItest\fP evaluates a predicate -and returns the result as its exit status. -Some of the more frequently used \fItest\fP -arguments are given here, see \fItest\fP (1) -for a complete specification. -.DS - test s true if the argument \fIs\fP is not the null string - test \(mif file true if \fIfile\fP exists - test \(mir file true if \fIfile\fP is readable - test \(miw file true if \fIfile\fP is writable - test \(mid file true if \fIfile\fP is a directory -.DE -.SH -2.6\ Control\ flow\ -\ while -.LP -The actions of -the \fBfor\fP loop and the \fBcase\fP -branch are determined by data available to the shell. -A \fBwhile\fP or \fBuntil\fP loop -and an \fBif then else\fP branch -are also provided whose -actions are determined by the exit status -returned by commands. -A \fBwhile\fP loop has the general form -.DS - \fBwhile\fP \fIcommand-list\*1\fP - \fBdo\fP \fIcommand-list\*2\fP - \fBdone\fP -.DE -.LP -The value tested by the \fBwhile\fP command -is the exit status of the last simple command -following \fBwhile.\fP -Each time round the loop -\fIcommand-list\*1\fP is executed; -if a zero exit status is returned then -\fIcommand-list\*2\fP -is executed; -otherwise, the loop terminates. -For example, -.DS - while test $1 - do \*(ZZ - \*(DOshift - done -.DE -is equivalent to -.DS - for i - do \*(ZZ - done -.DE -\fIshift\fP is a shell command that -renames the positional parameters -\fB$2, $3, \*(ZZ\fR as \fB$1, $2, \*(ZZ\fR -and loses \fB$1\|.\fP -.LP -Another kind of use for the \fBwhile/until\fP -loop is to wait until some -external event occurs and then run -some commands. -In an \fBuntil\fP loop -the termination condition is reversed. -For example, -.DS - until test \(mif file - do sleep 300; done - \fIcommands\fP -.DE -will loop until \fIfile\fP exists. -Each time round the loop it waits for -5 minutes before trying again. -(Presumably another process -will eventually create the file.) -.SH -2.7\ Control\ flow\ -\ if -.LP -Also available is a -general conditional branch -of the form, -.DS - \fBif\fP \fIcommand-list - \fBthen \fIcommand-list - \fBelse \fIcommand-list - \fBfi\fR -.DE -that tests the value returned by the last simple command -following \fBif.\fP -.LP -The \fBif\fP command may be used -in conjunction with the \fItest\fP command -to test for the existence of a file as in -.DS - if test \(mif file - then \fIprocess file\fP - else \fIdo something else\fP - fi -.DE -.LP -An example of the use of \fBif, case\fP -and \fBfor\fP constructions is given in -section 2.10\|. -.LP -A multiple test \fBif\fP command -of the form -.DS - if \*(ZZ - then \*(ZZ - else if \*(ZZ - then \*(ZZ - else if \*(ZZ - \*(ZZ - fi - fi - fi -.DE -may be written using an extension of the \fBif\fP -notation as, -.DS - if \*(ZZ - then \*(ZZ - elif \*(ZZ - then \*(ZZ - elif \*(ZZ - \*(ZZ - fi -.DE -.LP -The following example is the \fItouch\fP command -which changes the `last modified' time for a list -of files. -The command may be used in conjunction -with \fImake\fP (1) to force recompilation of a list -of files. -.DS - flag= - for i - do case $i in - \*(DC\(mic) flag=N ;; - \*(DC\*(ST) if test \(mif $i - \*(DC then ln $i junk$$; rm junk$$ - \*(DC elif test $flag - \*(DC then echo file \\\\\'$i\\\\\' does not exist - \*(DC else >$i - \*(DC fi - \*(DO esac - done -.DE -The \fB\(mic\fP flag is used in this command to -force subsequent files to be created if they do not already exist. -Otherwise, if the file does not exist, an error message is printed. -The shell variable \fIflag\fP -is set to some non-null string if the \fB\(mic\fP -argument is encountered. -The commands -.DS - ln \*(ZZ; rm \*(ZZ -.DE -make a link to the file and then remove it -thus causing the last modified date to be updated. -.LP -The sequence -.DS - if command1 - then command2 - fi -.DE -may be written -.DS - command1 && command2 -.DE -Conversely, -.DS - command1 \*(VT\*(VT command2 -.DE -executes \fIcommand2\fP only if \fIcommand1\fP -fails. -In each case the value returned -is that of the last simple command executed. -.SH -2.8\ Command\ grouping -.LP -Commands may be grouped in two ways, -.DS - \fB{\fI command-list\fB ; }\fR -.DE -and -.DS - \fB(\fI command-list\fB )\fR -.DE -.LP -In the first \fIcommand-list\fP is simply executed. -The second form executes \fIcommand-list\fP -as a separate process. -For example, -.DS - (cd x; rm junk ) -.DE -executes \fIrm junk\fP in the directory -\fBx\fP without changing the current -directory of the invoking shell. -.LP -The commands -.DS - cd x; rm junk -.DE -have the same effect but leave the invoking -shell in the directory \fBx.\fP -.SH -2.9\ Debugging\ shell\ procedures -.LP -The shell provides two tracing mechanisms -to help when debugging shell procedures. -The first is invoked within the procedure -as -.DS - set \(miv -.DE -(\fBv\fP for verbose) and causes lines of the -procedure to be printed as they are read. -It is useful to help isolate syntax errors. -It may be invoked without modifying the procedure -by saying -.DS - sh \(miv proc \*(ZZ -.DE -where \fIproc\fP is the name of the shell procedure. -This flag may be used in conjunction -with the \fB\(min\fP flag which prevents -execution of subsequent commands. -(Note that saying \fIset \(min\fP at a terminal -will render the terminal useless -until an end-of-file is typed.) -.LP -The command -.DS - set \(mix -.DE -will produce an execution -trace. -Following parameter substitution -each command is printed as it is executed. -(Try these at the terminal to see -what effect they have.) -Both flags may be turned off by saying -.DS - set \(mi -.DE -and the current setting of the shell flags is available as \fB$\(mi\|.\fR -.SH -2.10\ The\ man\ command -.LP -The following is the \fIman\fP command -which is used to print sections of the UNIX manual. -It is called, for example, as -.DS - man sh - man \(mit ed - man 2 fork -.DE -In the first the manual section for \fIsh\fP -is printed. -Since no section is specified, section 1 is used. -The second example will typeset (\fB\(mit\fP option) -the manual section for \fIed.\fP -The last prints the \fIfork\fP manual page -from section 2. -.sp 2 -.DS - cd /usr/man - - : \'colon is the comment command\' - : \'default is nroff ($N), section 1 ($s)\' - N=n\ s=1 - - for i - do case $i in -.sp .5 - \*(DC[1\(mi9]\*(ST) s=$i ;; -.sp .5 - \*(DC\(mit) N=t ;; -.sp .5 - \*(DC\(min) N=n ;; -.sp .5 - \*(DC\(mi\*(ST) echo unknown flag \\\\\'$i\\\\\' ;; -.sp .5 - \*(DC\*(ST) if test \(mif man$s/$i.$s - \*(DC then ${N}roff man0/${N}aa man$s/$i.$s - \*(DC else : \'look through all manual sections\' - \*(DC found=no - \*(DC for j in 1 2 3 4 5 6 7 8 9 - \*(DC do if test \(mif man$j/$i.$j - \*(DC \*(DOthen man $j $i - \*(DC \*(DO\*(THfound=yes - \*(DC \*(DOfi - \*(DC done - \*(DC case $found in - \*(DC \*(Cano) echo \\'$i: manual page not found\\' - \*(DC esac - \*(DC fi - \*(DOesac - done -.DE -.ce -.ft B -Figure 1. A version of the man command -.ft R //GO.SYSIN DD t2 echo t3 sed 's/.//' >t3 <<'//GO.SYSIN DD t3' -.bp -.SH -3.0\ Keyword\ parameters -.LP -Shell variables may be given values -by assignment -or when a shell procedure is invoked. -An argument to a shell procedure of the form -\fIname=value\fP -that precedes the command name -causes \fIvalue\fP -to be assigned to \fIname\fP -before execution of the procedure begins. -The value of \fIname\fP in the invoking -shell is not affected. -For example, -.DS - user=fred\ command -.DE -will execute \fIcommand\fP with -\fBuser\fP set to \fIfred\fP. -The \fB\(mik\fR flag causes arguments of the form -\fIname=value\fP to be interpreted in this way -anywhere in the argument list. -Such \fInames\fP are sometimes -called keyword parameters. -If any arguments remain they -are available as positional -parameters \fB$1, $2, \*(ZZ\|.\fP -.LP -The \fIset\fP command -may also be used to set positional parameters -from within a procedure. -For example, -.DS - set\ \(mi\ \*(ST -.DE -will set \fB$1\fP to the first file name -in the current directory, \fB$2\fP to the next, -and so on. -Note that the first argument, \(mi, ensures correct treatment -when the first file name begins with a \(mi\|. -.LP -.SH -3.1\ Parameter\ transmission -.LP -When a shell procedure is invoked both positional -and keyword parameters may be supplied with the call. -Keyword parameters are also made available implicitly -to a shell procedure -by specifying in advance that such parameters -are to be exported. -For example, -.DS - export\ user\ box -.DE -marks the variables \fBuser\fP and \fBbox\fP -for export. -When a shell procedure is invoked -copies are made of all exportable variables -for use within the invoked procedure. -Modification of such variables -within the procedure does not -affect the values in the invoking shell. -It is generally true of -a shell procedure -that it -may not modify the state -of its caller without explicit -request on the part of the caller. -(Shared file descriptors are an -exception to this rule.) -.LP -Names whose value is intended to remain -constant may be declared \fIreadonly\|.\fP -The form of this command is the same as that of the \fIexport\fP -command, -.DS - readonly name \*(ZZ -.DE -Subsequent attempts to set readonly variables -are illegal. -.SH -3.2\ Parameter\ substitution -.LP -If a shell parameter is not set -then the null string is substituted for it. -For example, if the variable \fBd\fP -is not set -.DS - echo $d -.DE -or -.DS - echo ${d} -.DE -will echo nothing. -A default string may be given -as in -.DS - echo ${d\(mi\fB.\fR} -.DE -which will echo -the value of the variable \fBd\fP -if it is set and `\fB.\fP' otherwise. -The default string is evaluated using the usual -quoting conventions so that -.DS - echo ${d\(mi\'\*(ST\'} -.DE -will echo \fB\*(ST\fP if the variable \fBd\fP -is not set. -Similarly -.DS - echo ${d\(mi$1} -.DE -will echo the value of \fBd\fP if it is set -and the value (if any) of \fB$1\fP otherwise. -A variable may be assigned a default value -using -the notation -.DS - echo ${d=\fB.\fR} -.DE -which substitutes the same string as -.DS - echo ${d\(mi\fB.\fR} -.DE -and if \fBd\fP were not previously set -then it will be set to the string `\fB.\fP'\|. -(The notation ${\*(ZZ=\*(ZZ} -is not available for positional parameters.) -.LP -If there is no sensible default then -the notation -.DS - echo ${d?message} -.DE -will echo the value of the variable \fBd\fP if it has -one, otherwise \fImessage\fP is printed by the shell and -execution of the shell procedure is abandoned. -If \fImessage\fP is absent then a standard message -is printed. -A shell procedure that requires some parameters -to be set might start as follows. -.DS - :\ ${user?}\ ${acct?}\ ${bin?} - \*(ZZ -.DE -Colon (\fB:\fP) is a command -that is -built in to the shell and does nothing -once its arguments have been evaluated. -If any of the variables \fBuser, acct\fP -or \fBbin\fP are not set then the shell -will abandon execution of the procedure. -.SH -3.3\ Command\ substitution -.LP -The standard output from a command can be -substituted in a similar way to parameters. -The command \fIpwd\fP prints on its standard -output the name of the current directory. -For example, if the current directory is -\fB/usr/fred/bin\fR -then the command -.DS - d=\`pwd\` -.DE -is equivalent to -.DS - d=/usr/fred/bin -.DE -.LP -The entire string between grave accents (\`\*(ZZ\`) -is taken as the command -to be executed -and is replaced with the output from -the command. -The command is written using the usual -quoting conventions -except that a \fB\`\fR must be escaped using -a \fB\\\|.\fR -For example, -.DS - ls \`echo "$1"\` -.DE -is equivalent to -.DS - ls $1 -.DE -Command substitution occurs in all contexts -where parameter substitution occurs (including \fIhere\fP documents) and the -treatment of the resulting text is the same -in both cases. -This mechanism allows string -processing commands to be used within -shell procedures. -An example of such a command is \fIbasename\fP -which removes a specified suffix from a string. -For example, -.DS - basename main\fB.\fPc \fB.\fPc -.DE -will print the string \fImain\|.\fP -Its use is illustrated by the following -fragment from a \fIcc\fP command. -.DS - case $A in - \*(Ca\*(ZZ - \*(Ca\*(ST\fB.\fPc) B=\`basename $A \fB.\fPc\` - \*(Ca\*(ZZ - esac -.DE -that sets \fBB\fP to the part of \fB$A\fP -with the suffix \fB.c\fP stripped. -.LP -Here are some composite examples. -.RS -.IP \(bu -.ft B -for i in \`ls \(mit\`; do \*(ZZ -.ft R -.br -The variable \fBi\fP is set -to the names of files in time order, -most recent first. -.IP \(bu -.ft B -set \`date\`; echo $6 $2 $3, $4 -.ft R -.br -will print, e.g., -.ft I -1977 Nov 1, 23:59:59 -.ft R -.RE -.SH -3.4\ Evaluation\ and\ quoting -.LP -The shell is a macro processor that -provides parameter substitution, command substitution and file -name generation for the arguments to commands. -This section discusses the order in which -these evaluations occur and the -effects of the various quoting mechanisms. -.LP -Commands are parsed initially according to the grammar -given in appendix A. -Before a command is executed -the following -substitutions occur. -.RS -.IP \(bu -parameter substitution, e.g. \fB$user\fP -.IP \(bu -command substitution, e.g. \fB\`pwd\`\fP -.RS -.LP -Only one evaluation occurs so that if, for example, the value of the variable -\fBX\fP -is the string \fI$y\fP -then -.DS - echo $X -.DE -will echo \fI$y\|.\fP -.RE -.IP \(bu -blank interpretation -.RS -.LP -Following the above substitutions -the resulting characters -are broken into non-blank words (\fIblank interpretation\fP). -For this purpose `blanks' are the characters of the string -\fB$\s-1IFS\s0\fP. -By default, this string consists of blank, tab and newline. -The null string -is not regarded as a word unless it is quoted. -For example, -.DS - echo \'\' -.DE -will pass on the null string as the first argument to \fIecho\fP, -whereas -.DS - echo $null -.DE -will call \fIecho\fR with no arguments -if the variable \fBnull\fP is not set -or set to the null string. -.RE -.IP \(bu -file name generation -.RS -.LP -Each word -is then scanned for the file pattern characters -\fB\*(ST, ?\fR and \fB[\*(ZZ]\fR -and an alphabetical list of file names -is generated to replace the word. -Each such file name is a separate argument. -.RE -.RE -.LP -The evaluations just described also occur -in the list of words associated with a \fBfor\fP -loop. -Only substitution occurs -in the \fIword\fP used -for a \fBcase\fP branch. -.LP -As well as the quoting mechanisms described -earlier using \fB\\\fR and \fB\'\*(ZZ\'\fR -a third quoting mechanism is provided using double quotes. -Within double quotes parameter and command substitution -occurs but file name generation and the interpretation -of blanks does not. -The following characters -have a special meaning within double quotes -and may be quoted using \fB\\\|.\fP -.DS - \fB$ \fPparameter substitution - \fB\`\fP command substitution - \fB"\fP ends the quoted string - \fB\e\fP quotes the special characters \fB$ \` " \e\fP -.DE -For example, -.DS - echo "$x" -.DE -will pass the value of the variable \fBx\fP as a -single argument to \fIecho.\fP -Similarly, -.DS - echo "$\*(ST" -.DE -will pass the positional parameters as a single -argument and is equivalent to -.DS - echo "$1 $2 \*(ZZ" -.DE -The notation \fB$@\fP -is the same as \fB$\*(ST\fR -except when it is quoted. -.DS - echo "$@" -.DE -will pass the positional parameters, unevaluated, to \fIecho\fR -and is equivalent to -.DS - echo "$1" "$2" \*(ZZ -.DE -.LP -The following table gives, for each quoting mechanism, -the shell metacharacters that are evaluated. -.DS -.ce -.ft I -metacharacter -.ft -.in 1.5i - \e $ * \` " \' -\' n n n n n t -\` y n n t n n -" y y n y t n - - t terminator - y interpreted - n not interpreted - -.in -.ft B -.ce -Figure 2. Quoting mechanisms -.ft -.DE -.LP -In cases where more than one evaluation of a string -is required the built-in command \fIeval\fP -may be used. -For example, -if the variable \fBX\fP has the value -\fI$y\fP, and if \fBy\fP has the value \fIpqr\fP -then -.DS - eval echo $X -.DE -will echo the string \fIpqr\|.\fP -.LP -In general the \fIeval\fP command -evaluates its arguments (as do all commands) -and treats the result as input to the shell. -The input is read and the resulting command(s) -executed. -For example, -.DS - wg=\\'eval who\*(VTgrep\\' - $wg fred -.DE -is equivalent to -.DS - who\*(VTgrep fred -.DE -In this example, -\fIeval\fP is required -since there is no interpretation -of metacharacters, such as \fB\*(VT\|,\fP following -substitution. -.SH -3.5\ Error\ handling -.LP -The treatment of errors detected by -the shell depends on the type of error -and on whether the shell is being -used interactively. -An interactive shell is one whose -input and output are connected -to a terminal (as determined by -\fIgtty\fP (2)). -A shell invoked with the \fB\(mii\fP -flag is also interactive. -.LP -Execution of a command (see also 3.7) may fail -for any of the following reasons. -.IP \(bu -Input output redirection may fail. -For example, if a file does not exist -or cannot be created. -.IP \(bu -The command itself does not exist -or cannot be executed. -.IP \(bu -The command terminates abnormally, -for example, with a "bus error" -or "memory fault". -See Figure 2 below for a complete list -of UNIX signals. -.IP \(bu -The command terminates normally -but returns a non-zero exit status. -.LP -In all of these cases the shell -will go on to execute the next command. -Except for the last case an error -message will be printed by the shell. -All remaining errors cause the shell -to exit from a command procedure. -An interactive shell will return -to read another command from the terminal. -Such errors include the following. -.IP \(bu -Syntax errors. -e.g., if \*(ZZ then \*(ZZ done -.IP \(bu -A signal such as interrupt. -The shell waits for the current -command, if any, to finish execution and -then either exits or returns to the terminal. -.IP \(bu -Failure of any of the built-in commands -such as \fIcd.\fP -.LP -The shell flag \fB\(mie\fP -causes the shell to terminate -if any error is detected. -.DS -1 hangup -2 interrupt -3* quit -4* illegal instruction -5* trace trap -6* IOT instruction -7* EMT instruction -8* floating point exception -9 kill (cannot be caught or ignored) -10* bus error -11* segmentation violation -12* bad argument to system call -13 write on a pipe with no one to read it -14 alarm clock -15 software termination (from \fIkill\fP (1)) - -.DE -.ft B -.ce -Figure 3. UNIX signals -.ft - -Those signals marked with an asterisk -produce a core dump -if not caught. -However, -the shell itself ignores quit which is the only -external signal that can cause a dump. -The signals in this list of potential interest -to shell programs are 1, 2, 3, 14 and 15. -.SH -3.6\ Fault\ handling -.LP -Shell procedures normally terminate -when an interrupt is received from the -terminal. -The \fItrap\fP command is used -if some cleaning up is required, such -as removing temporary files. -For example, -.DS - trap\ \'rm\ /tmp/ps$$; exit\'\ 2 -.DE -sets a trap for signal 2 (terminal -interrupt), and if this signal is received -will execute the commands -.DS - rm /tmp/ps$$; exit -.DE -\fIexit\fP is -another built-in command -that terminates execution of a shell procedure. -The \fIexit\fP is required; otherwise, -after the trap has been taken, -the shell will resume executing -the procedure -at the place where it was interrupted. -.LP -UNIX signals can be handled in one of three ways. -They can be ignored, in which case -the signal is never sent to the process. -They can be caught, in which case the process -must decide what action to take when the -signal is received. -Lastly, they can be left to cause -termination of the process without -it having to take any further action. -If a signal is being ignored -on entry to the shell procedure, for example, -by invoking it in the background (see 3.7) then \fItrap\fP -commands (and the signal) are ignored. -.LP -The use of \fItrap\fP is illustrated -by this modified version of the \fItouch\fP -command (Figure 4). -The cleanup action is to remove the file \fBjunk$$\fR\|. -.DS - flag= - trap\ \'rm\ \(mif\ junk$$;\ exit\'\ 1 2 3 15 - for i - do\ case\ $i\ in - \*(DC\(mic) flag=N ;; - \*(DC\*(ST) if\ test\ \(mif\ $i - \*(DC then ln\ $i\ junk$$;\ rm\ junk$$ - \*(DC elif\ test\ $flag - \*(DC then echo\ file\ \\\\\'$i\\\\\'\ does\ not\ exist - \*(DC else >$i - \*(DC fi - \*(DOesac - done -.DE -.sp -.ft B -.ce -Figure 4. The touch command -.ft -.sp -The \fItrap\fP command -appears before the creation -of the temporary file; -otherwise it would be -possible for the process -to die without removing -the file. -.LP -Since there is no signal 0 in UNIX -it is used by the shell to indicate the -commands to be executed on exit from the -shell procedure. -.LP -A procedure may, itself, elect to -ignore signals by specifying the null -string as the argument to trap. -The following fragment is taken from the -\fInohup\fP command. -.DS - trap \'\' 1 2 3 15 -.DE -which causes \fIhangup, interrupt, quit \fRand\fI kill\fR -to be ignored both by the -procedure and by invoked commands. -.LP -Traps may be reset by saying -.DS - trap 2 3 -.DE -which resets the traps for signals 2 and 3 to their default values. -A list of the current values of traps may be obtained -by writing -.DS - trap -.DE -.LP -The procedure \fIscan\fP (Figure 5) is an example -of the use of \fItrap\fP where there is no exit -in the trap command. -\fIscan\fP takes each directory -in the current directory, prompts -with its name, and then executes -commands typed at the terminal -until an end of file or an interrupt is received. -Interrupts are ignored while executing -the requested commands but cause -termination when \fIscan\fP is -waiting for input. -.DS - d=\`pwd\` - for\ i\ in\ \*(ST - do\ if\ test\ \(mid\ $d/$i - \*(DOthen\ cd\ $d/$i - \*(DO\*(THwhile\ echo\ "$i:" - \*(DO\*(TH\*(WHtrap\ exit\ 2 - \*(DO\*(TH\*(WHread\ x - \*(DO\*(THdo\ trap\ :\ 2;\ eval\ $x;\ done - \*(DOfi - done -.DE -.sp -.ft B -.ce -Figure 5. The scan command -.ft -.sp -\fIread x\fR is a built-in command that reads one line from the -standard input -and places the result in the variable \fBx\|.\fP -It returns a non-zero exit status if either -an end-of-file is read or an interrupt -is received. -.SH -3.7\ Command\ execution -.LP -To run a command (other than a built-in) the shell first creates -a new process using the system call \fIfork.\fP -The execution environment for the command -includes input, output and the states of signals, and -is established in the child process -before the command is executed. -The built-in command \fIexec\fP -is used in the rare cases when no fork -is required -and simply replaces the shell with a new command. -For example, a simple version of the \fInohup\fP -command looks like -.DS - trap \\'\\' 1 2 3 15 - exec $\*(ST -.DE -The \fItrap\fP turns off the signals specified -so that they are ignored by subsequently created commands -and \fIexec\fP replaces the shell by the command -specified. -.LP -Most forms of input output redirection have already been -described. -In the following \fIword\fP is only subject -to parameter and command substitution. -No file name generation or blank interpretation -takes place so that, for example, -.DS - echo \*(ZZ >\*(ST.c -.DE -will write its output into a file whose name is \fB\*(ST.c\|.\fP -Input output specifications are evaluated left to right -as they appear in the command. -.IP >\ \fIword\fP 12 -The standard output (file descriptor 1) -is sent to the file \fIword\fP which is -created if it does not already exist. -.IP \*(AP\ \fIword\fP 12 -The standard output is sent to file \fIword.\fP -If the file exists then output is appended -(by seeking to the end); -otherwise the file is created. -.IP <\ \fIword\fP 12 -The standard input (file descriptor 0) -is taken from the file \fIword.\fP -.IP \*(HE\ \fIword\fP 12 -The standard input is taken from the lines -of shell input that follow up to but not -including a line consisting only of \fIword.\fP -If \fIword\fP is quoted then no interpretation -of the document occurs. -If \fIword\fP is not quoted -then parameter and command substitution -occur and \fB\\\fP is used to quote -the characters \fB\\\fP \fB$\fP \fB\`\fP and the first character -of \fIword.\fP -In the latter case \fB\\newline\fP is ignored (c.f. quoted strings). -.IP >&\ \fIdigit\fP 12 -The file descriptor \fIdigit\fP is duplicated using the system -call \fIdup\fP (2) -and the result is used as the standard output. -.IP <&\ \fIdigit\fP 12 -The standard input is duplicated from file descriptor \fIdigit.\fP -.IP <&\(mi 12 -The standard input is closed. -.IP >&\(mi 12 -The standard output is closed. -.LP -Any of the above may be preceded by a digit in which -case the file descriptor created is that specified by the digit -instead of the default 0 or 1. -For example, -.DS - \*(ZZ 2>file -.DE -runs a command with message output (file descriptor 2) -directed to \fIfile.\fP -.DS - \*(ZZ 2>&1 -.DE -runs a command with its standard output and message output -merged. -(Strictly speaking file descriptor 2 is created -by duplicating file descriptor 1 but the effect is usually to -merge the two streams.) -.LP -The environment for a command run in the background such as -.DS - list \*(ST.c \*(VT lpr & -.DE -is modified in two ways. -Firstly, the default standard input -for such a command is the empty file \fB/dev/null\|.\fR -This prevents two processes (the shell and the command), -which are running in parallel, from trying to -read the same input. -Chaos would ensue -if this were not the case. -For example, -.DS - ed file & -.DE -would allow both the editor and the shell -to read from the same input at the same time. -.LP -The other modification to the environment of a background -command is to turn off the QUIT and INTERRUPT signals -so that they are ignored by the command. -This allows these signals to be used -at the terminal without causing background -commands to terminate. -For this reason the UNIX convention -for a signal is that if it is set to 1 -(ignored) then it is never changed -even for a short time. -Note that the shell command \fItrap\fP -has no effect for an ignored signal. -.SH -3.8\ Invoking\ the\ shell -.LP -The following flags are interpreted by the shell -when it is invoked. -If the first character of argument zero is a minus, -then commands are read from the file \fB.profile\|.\fP -.IP \fB\(mic\fP\ \fIstring\fP -.br -If the \fB\(mic\fP flag is present then -commands are read from \fIstring\|.\fP -.IP \fB\(mis\fP -If the \fB\(mis\fP flag is present or if no -arguments remain -then commands are read from the standard input. -Shell output is written to -file descriptor 2. -.IP \fB\(mii\fP -If the \fB\(mii\fP flag is present or -if the shell input and output are attached to a terminal (as told by \fIgtty\fP) -then this shell is \fIinteractive.\fP -In this case TERMINATE is ignored (so that \fBkill 0\fP -does not kill an interactive shell) and INTERRUPT is caught and ignored -(so that \fBwait\fP is interruptable). -In all cases QUIT is ignored by the shell. -.SH -Acknowledgements -.LP -The design of the shell is -based in part on the original UNIX shell -.[ -unix command language thompson -.] -and the PWB/UNIX shell, -.[ -pwb shell mashey unix -.] -some -features having been taken from both. -Similarities also exist with the -command interpreters -of the Cambridge Multiple Access System -.[ -cambridge multiple access system hartley -.] -and of CTSS. -.[ -ctss -.] -.LP -I would like to thank Dennis Ritchie -and John Mashey for many -discussions during the design of the shell. -I am also grateful to the members of the Computing Science Research Center -and to Joe Maranzano for their -comments on drafts of this document. -.SH -.[ -$LIST$ -.] //GO.SYSIN DD t3 echo t4 sed 's/.//' >t4 <<'//GO.SYSIN DD t4' -.bp -.SH -Appendix\ A\ -\ Grammar -.LP -.DS -\fIitem: word - input-output - name = value -.sp 0.8 -simple-command: item - simple-command item -.sp 0.8 -command: simple-command - \fB( \fIcommand-list \fB) - \fB{ \fIcommand-list \fB} - \fBfor \fIname \fBdo \fIcommand-list \fBdone - \fBfor \fIname \fBin \fIword \*(ZZ \fBdo \fIcommand-list \fBdone - \fBwhile \fIcommand-list \fBdo \fIcommand-list \fBdone - \fBuntil \fIcommand-list \fBdo \fIcommand-list \fBdone - \fBcase \fIword \fBin \fIcase-part \*(ZZ \fBesac - \fBif \fIcommand-list \fBthen \fIcommand-list \fIelse-part \fBfi -.sp 0.8 -\fIpipeline: command - pipeline \fB\*(VT\fI command -.sp 0.8 -andor: pipeline - andor \fB&&\fI pipeline - andor \fB\*(VT\*(VT\fI pipeline -.sp 0.8 -command-list: andor - command-list \fB;\fI - command-list \fB&\fI - command-list \fB;\fI andor - command-list \fB&\fI andor -.sp 0.8 -input-output: \fB> \fIfile - \fB< \fIfile - \fB\*(AP \fIword - \fB\*(HE \fIword -.sp 0.8 -file: word - \fB&\fI digit - \fB&\fI \(mi -.sp 0.8 -case-part: pattern\fB ) \fIcommand-list\fB ;; -.sp 0.8 -\fIpattern: word - pattern \fB\*(VT\fI word -.sp 0.8 -\fIelse-part: \fBelif \fIcommand-list\fB then\fI command-list else-part\fP - \fBelse \fIcommand-list\fI - empty -.sp 0.8 -empty: -.sp 0.8 -word: \fRa sequence of non-blank characters\fI -.sp 0.8 -name: \fRa sequence of letters, digits or underscores starting with a letter\fI -.sp 0.8 -digit: \fB0 1 2 3 4 5 6 7 8 9\fP -.DE -.LP -.bp -.SH -Appendix\ B\ -\ Meta-characters\ and\ Reserved\ Words -.LP -a) syntactic -.RS -.IP \fB\*(VT\fR 6 -pipe symbol -.IP \fB&&\fR 6 -`andf' symbol -.IP \fB\*(VT\*(VT\fR 6 -`orf' symbol -.IP \fB;\fP 6 -command separator -.IP \fB;;\fP 6 -case delimiter -.IP \fB&\fP 6 -background commands -.IP \fB(\ )\fP 6 -command grouping -.IP \fB<\fP 6 -input redirection -.IP \fB\*(HE\fP 6 -input from a here document -.IP \fB>\fP 6 -output creation -.IP \fB\*(AP\fP 6 -output append -.sp 2 -.RE -.LP -b) patterns -.RS -.IP \fB\*(ST\fP 6 -match any character(s) including none -.IP \fB?\fP 6 -match any single character -.IP \fB[...]\fP 6 -match any of the enclosed characters -.sp 2 -.RE -.LP -c) substitution -.RS -.IP \fB${...}\fP 6 -substitute shell variable -.IP \fB\`...\`\fP 6 -substitute command output -.sp 2 -.RE -.LP -d) quoting -.RS -.IP \fB\e\fP 6 -quote the next character -.IP \fB\'...\'\fP 6 -quote the enclosed characters except for \' -.IP \fB"\&..."\fR 6 -quote the enclosed characters except -for \fB$ \` \e "\fP -.sp 2 -.RE -.LP -e) reserved words -.DS -.ft B -if then else elif fi -case in esac -for while until do done -{ } -.ft -.DE //GO.SYSIN DD t4