Module Name: src Committed By: perry Date: Sun Aug 22 02:03:07 UTC 2010
Modified Files: src/bin/sh/USD.doc: t1 t2 t3 t4 Log Message: Extremely extensive updates. This document should now serve as a reasonable tutorial for the modern POSIX shell. Comments and additional fixes for mistakes I may have made are solicited. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/bin/sh/USD.doc/t1 src/bin/sh/USD.doc/t2 \ src/bin/sh/USD.doc/t3 src/bin/sh/USD.doc/t4 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/bin/sh/USD.doc/t1 diff -u src/bin/sh/USD.doc/t1:1.1 src/bin/sh/USD.doc/t1:1.2 --- src/bin/sh/USD.doc/t1:1.1 Sun Aug 22 01:58:16 2010 +++ src/bin/sh/USD.doc/t1 Sun Aug 22 02:03:06 2010 @@ -14,7 +14,7 @@ .\" documentation and/or other materials provided with the distribution. .\" .\" All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: +.\" must display the following acknowledgment: .\" .\" This product includes software developed or owned by Caldera .\" International, Inc. Neither the name of Caldera International, Inc. @@ -40,7 +40,7 @@ .EH 'USD:3-%''An Introduction to the UNIX Shell' .OH 'An Introduction to the UNIX Shell''USD:3-%' .\".RP -.TL +.TL An Introduction to the UNIX Shell .AU S. R. Bourne @@ -48,15 +48,23 @@ Murray Hill, NJ .AU (Updated for 4.3BSD by Mark Seiden) +.AU +(Further updated by Perry E. Metzger)\(dg .AB +.FS +\(dg This paper was updated in 2010 to reflect most features of modern +POSIX shells, which all follow the design of S.R. Bourne's original v7 +Unix shell. +Among these are ash, bash, ksh and others. +Typically one of these will be installed as /bin/sh on a modern system. +It does not describe the behavior of the c shell (csh). +If it's the c shell (csh) you're interested in, a good place to +begin is William Joy's paper "An Introduction to the C shell" (USD:4). +.FE .LP The .ul -shell\(dd -.FS -\(dd This paper describes sh(1). If it's the c shell (csh) you're interested in, -a good place to begin is William Joy's paper "An Introduction to the C shell" (USD:4). -.FE +shell is a command programming language that provides an interface to the .UX @@ -156,28 +164,7 @@ 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 +1.2\ Input\ output\ redirection .LP Most commands produce output on the standard output that is initially connected to the terminal. @@ -218,8 +205,30 @@ wc \(mil <file .DE could be used. +.\" I considered adding the following, but have thought better of it +.\" for now. +.\" -- Perry Metzger +.\" +.\" .LP +.\" Error messages are typically printed by commands on a different +.\" channel, called standard error, which may also be redirected using the +.\" notation 2>\|. +.\" For example +.\" .DS +.\" command some args >out 2>errors +.\" .DE +.\" will redirect standard output to the file `out' but standard error +.\" (and thus all error messages) to `errors'. +.\" The notation 2>&1 sets standard error pointing to the same +.\" place as standard out. +.\" Thus: +.\" .DS +.\" command some args 2>&1 >everything +.\" .DE +.\" will put both standard out and standard error into the file `everything'. +.\" See section 3.7 below for more details. .SH -1.4\ Pipelines\ and\ filters +1.3\ Pipelines\ and\ filters .LP The standard output of one command may be connected to the standard input of another @@ -237,8 +246,8 @@ ls \(mil >file; wc <file .DE except that no \fIfile\fP is used. -Instead the two processes are connected -by a pipe (see \fIpipe\fP (2)) and are +Instead the two \fIprocesses\fP are connected +by a pipe (see \fIpipe\fP(2)) and are run in parallel. Pipes are unidirectional and synchronization is achieved by @@ -277,6 +286,37 @@ in the current directory containing the string \fIold.\fP .SH +1.4\ Background\ commands +.LP +To execute a command (or pipeline) the shell normally +creates the new \fIprocesses\fP +and waits for them 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 job number (see below) and process +id following its creation. +Such a command is said to be running in the \fIbackground\fP. +By contrast, a command executed without the \fB&\fP is said to be +running in the \fIforeground\fP.\(dg +.FS +\(dg Even after execution, one may move commands from the foreground +to the background, or temporarily suspend their execution (which is +known as \fIstopping\fP a command. +This is described in detail in section 3.10 on \fIJob Control\fB. +.FE +.LP +A list of currently active processes, including ones not associated +with the current shell, may be obtained using the \fIps\fP(1) command. +.SH 1.5\ File\ name\ generation .LP Many commands accept arguments @@ -367,6 +407,21 @@ respectively. (Notice that \fIls\fP suppresses information for the files `\fB.\fP' and `\fB..\fP'\|.) +.LP +Finally, the tilde character, `\fB\(ap\fP', may be used to indicate the +home directory of a user. +The `\fB\(ap\fP' at the beginning of a path name followed by a +non-alphabetic character expands to the current user's home +directory. +If the `\fB\(ap\fP' is followed by a login name, it expands to the named +user's home directory. +For example: +.DS + ls \(ap + cd \(apegbert/ +.DE +will list the contents of the user's home directory and then change +to the home directory of the user ``egbert''. .SH 1.6\ Quoting .LP @@ -379,12 +434,12 @@ and loses its special meaning, if any. The \fB\\\fP is elided so that .DS - echo \\\\? + echo \\? .DE will echo a single \fB?\|,\fP and .DS - echo \\\\\\\\ + echo \\\\ .DE will echo a single \fB\\\|.\fR To allow long strings to be continued over @@ -420,7 +475,7 @@ metacharacters. Discussion of the details is deferred -to section 3.4\|. +to section 3.5\|. .SH 1.7\ Prompting .LP @@ -430,23 +485,29 @@ It may be changed by saying, for example, .DS - \s-1PS1\s0=yesdear + \s-1PS1\s0="yesdear$ " .DE -that sets the prompt to be the string \fIyesdear\|.\fP +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) +If it is unexpected then entering the interrupt character +(typically \s-1CONTROL-C\s0) will return the shell to read another command. This prompt may be changed by saying, for example, .DS \s-1PS2\s0=more .DE +Entering the interrupt character may also be used to terminate most +programs running as the current foreground job. +.LP +(\s-1PS1\s0 and \s-1PS2\s0 are \fIshell variables\fP, which will be +described in section 2.4 below.) .SH 1.8\ The\ shell\ and\ login .LP -Following \fIlogin\fP (1) +Following \fIlogin\fP(1) the shell is called to read and execute commands typed at the terminal. If the user's login directory @@ -454,6 +515,12 @@ then it is assumed to contain commands and is read by the shell before reading any commands from the terminal. +.LP +(Most versions of the shell also specify a file that is read and +executed on start-up whether or not the shell is invoked by login. +The \s-1ENV\s0 shell variable, described in section 2.4 below, can be +used to override the name of this file. +See the shell manual page for further information.) .SH 1.9\ Summary .sp Index: src/bin/sh/USD.doc/t2 diff -u src/bin/sh/USD.doc/t2:1.1 src/bin/sh/USD.doc/t2:1.2 --- src/bin/sh/USD.doc/t2:1.1 Sun Aug 22 01:58:17 2010 +++ src/bin/sh/USD.doc/t2 Sun Aug 22 02:03:06 2010 @@ -14,7 +14,7 @@ .\" documentation and/or other materials provided with the distribution. .\" .\" All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: +.\" must display the following acknowledgment: .\" .\" This product includes software developed or owned by Caldera .\" International, Inc. Neither the name of Caldera International, Inc. @@ -38,7 +38,7 @@ .\" @(#)t2 8.1 (Berkeley) 6/8/93 .\" .SH -2.0\ Shell\ procedures +2.0\ Shell\ scripts .LP The shell may be used to read and execute commands contained in a file. @@ -47,12 +47,12 @@ 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 +Such a file is called a \fIshell script.\fP Arguments may be supplied with the call and are referred to in \fIfile\fP using the positional parameters \fB$1, $2, \*(ZZ\|.\fR +.LP For example, if the file \fIwg\fP contains .DS who \*(VT grep $1 @@ -68,7 +68,7 @@ .LP UNIX files have three independent attributes, \fIread,\fP \fIwrite\fP and \fIexecute.\fP -The UNIX command \fIchmod\fP (1) may be used +The UNIX command \fIchmod\fP(1) may be used to make a file executable. For example, .DS @@ -83,14 +83,31 @@ .DS sh wg fred .DE -This allows shell procedures and programs +This allows shell scripts and other programs to be used interchangeably. In either case a new process is created to run the command. .LP +The `\fB#\fP' character is used as a comment character by the shell. +All characters following the `#' on a line are ignored. +.LP +A typical modern system has several different shells, some with differing +command syntax, and it is desirable to specify which one should be +invoked when an executable script is invoked. +If the special comment +.DS + #!/\fIpath\fP/\fIto\fP/\fIinterpreter\fP +.DE +appears as the first line in a script, it is used to specify the +absolute pathname of the shell (or other interpreter) that should be +used to execute the file. +(Without such a line, \fB/bin/sh\fP is assumed.) +It is best if a script explicitly states +what shell it is intended for in this manner. +.LP As well as providing names for the positional parameters, -the number of positional parameters in the call +the number of positional parameters to a script is available as \fB$#\|.\fP The name of the file being executed is available as \fB$0\|.\fP @@ -106,15 +123,18 @@ .DE which simply prepends some arguments to those already given. +(The variable \...@\fp also expands to ``all positional +parameters'', but is subtly different when expanded inside quotes. +See section 3.5, below.) .SH 2.1\ Control\ flow\ -\ for .LP -A frequent use of shell procedures is to loop +A frequent use of shell scripts is to loop through the arguments (\fB$1, $2, \*(ZZ\fR) executing commands once for each argument. -An example of such a procedure is +An example of such a script is \fItel\fP that searches the file -\fB/usr/lib/telnos\fR +\fB/usr/share/telnos\fR that contains lines of the form .DS \*(ZZ @@ -124,14 +144,18 @@ .DE The text of \fItel\fP is .DS + #!/bin/sh + for i - do grep $i /usr/lib/telnos; done + do + grep $i /usr/share/telnos + done .DE The command .DS tel fred .DE -prints those lines in \fB/usr/lib/telnos\fR +prints those lines in \fB/usr/share/telnos\fR that contain the string \fIfred\|.\fP .DS tel fred bert @@ -187,7 +211,7 @@ case $# in \*(Ca1) cat \*(AP$1 ;; \*(Ca2) cat \*(AP$2 <$1 ;; - \*(Ca\*(ST) echo \\'usage: append [ from ] to\\' ;; + \*(Ca\*(ST) echo \'usage: append [ from ] to\' ;; esac .DE is an \fIappend\fP command. @@ -253,9 +277,9 @@ for i do case $i in \*(DC\(mi[ocs]) \*(ZZ ;; - \*(DC\(mi\*(ST) echo \\"unknown flag $i\\" ;; + \*(DC\(mi\*(ST) echo "unknown flag $i" ;; \*(DC\*(ST.c) /lib/c0 $i \*(ZZ ;; - \*(DC\*(ST) echo \\"unexpected argument $i\\" ;; + \*(DC\*(ST) echo "unexpected argument $i" ;; \*(DOesac done .DE @@ -282,19 +306,19 @@ so that .DS case $i in - \*(Ca\\\\?) \*(ZZ + \*(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 +The shell script \fItel\fP +in section 2.1 uses the file \fB/usr/share/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, +within the shell script as a \fIhere\fP document, as in, .DS for i do grep $i \*(HE! @@ -314,7 +338,7 @@ .LP Parameters are substituted in the document before it is made available to \fIgrep\fP -as illustrated by the following procedure +as illustrated by the following script called \fIedg\|.\fP .DS ed $3 \*(HE% @@ -340,7 +364,7 @@ as in .DS ed $3 \*(HE+ - 1,\\\\$s/$1/$2/g + 1,\\$s/$1/$2/g w + .DE @@ -353,9 +377,9 @@ the terminating string, for example, .DS - grep $i \*(HE\\\\# + grep $i \*(HE'end' \*(ZZ - # + end .DE The document is presented without modification to \fIgrep.\fP @@ -363,8 +387,11 @@ in a \fIhere\fP document this latter form is more efficient. .SH -2.4\ Shell\ variables +2.4\ Shell\ variables\(dg .LP +.FS +Also known as \fIenvironment variables\fB, see \fIenvironment\fB(7). +.FE The shell provides string-valued variables. Variable names begin with a letter @@ -382,7 +409,7 @@ null= .DE The value of a variable is substituted -by preceding its name with \fB$\|;\fP +by preceding its name with \fB$\|\fP; for example, .DS echo $user @@ -511,6 +538,8 @@ .DE This variable is also typically set in the the user's login profile. +.IP \fB$\s-1PWD\s0\fP 8 +The current working directory. Set by the \fIcd\fB command. .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 @@ -545,7 +574,14 @@ by default, `\fB>\ \fR'. .IP \fB$\s-1IFS\s0\fP 8 The set of characters used by \fIblank -interpretation\fR (see section 3.4). +interpretation\fR (see section 3.5). +.IP \fB$\s-1ENV\s0\fP 8 +The shell reads and executes the commands in the file +specified by this variable when it is initially started. +Unlike the \fB.profile\fP file, these commands are executed by all +shells, not just the one started at login. +(Most versions of the shell specify a filename that is used if +\s-1ENV\s0 is not explicitly set. See the manual page for your shell.) .RE .SH 2.5\ The\ test\ command @@ -561,7 +597,7 @@ 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) +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 @@ -570,6 +606,20 @@ test \(miw file true if \fIfile\fP is writable test \(mid file true if \fIfile\fP is a directory .DE +The \fItest\fP command is known as `\fB[\fP' and may be invoked as +such. +For aesthetic reasons, the command ignores a close bracket `\fB]\fP' given +at the end of a command so +.DS + [ -f filename ] +.DE +and +.DS + test -f filename +.DE +are completely equivalent. +Typically, the bracket notation is used when \fItest\fP is invoked inside +shell control constructs. .SH 2.6\ Control\ flow\ -\ while .LP @@ -599,7 +649,7 @@ otherwise, the loop terminates. For example, .DS - while test $1 + while [ $1 ] do \*(ZZ \*(DOshift done @@ -623,7 +673,7 @@ the termination condition is reversed. For example, .DS - until test \(mif file + until [ \(mif file ] do sleep 300; done \fIcommands\fP .DE @@ -632,6 +682,20 @@ 5 minutes before trying again. (Presumably another process will eventually create the file.) +.LP +The most recent enclosing loop may be exited with the \fBbreak\fP +command, or the rest of the body skipped and the next iteration begun +with the \fBcontinue\fP command. +.LP +The commands \fItrue\fP(1) and \fIfalse\fP(1) return 0 and non-zero +exit statuses respectively. They are sometimes of use in control flow, +e.g.: +.DS + while true + do date; sleep 5 + done +.DE +is an infinite loop that prints the date and time every five seconds. .SH 2.7\ Control\ flow\ -\ if .LP @@ -651,7 +715,7 @@ in conjunction with the \fItest\fP command to test for the existence of a file as in .DS - if test \(mif file + if [ \(mif file ] then \fIprocess file\fP else \fIdo something else\fP fi @@ -686,21 +750,23 @@ fi .DE .LP -The following example is the \fItouch\fP command +The following example is an implementation of 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 +with \fImake\fP(1) to force recompilation of a list of files. .DS + #!/bin/sh + 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\*(ST) if [ \(mif $i ] + \*(DC then cp $i junk$$; mv junk$$ $i + \*(DC elif [ $flag ] + \*(DC then echo file \\'$i\\' does not exist \*(DC else >$i \*(DC fi \*(DO esac @@ -714,9 +780,9 @@ argument is encountered. The commands .DS - ln \*(ZZ; rm \*(ZZ + cp \*(ZZ; mv \*(ZZ .DE -make a link to the file and then remove it +copy the file and then overwrite it with the copy, thus causing the last modified date to be updated. .LP The sequence @@ -737,6 +803,17 @@ fails. In each case the value returned is that of the last simple command executed. +.LP +Placing a `\fB!\fP' in front of a pipeline inverts its exit +status, almost in the manner of the C operator of the same name. +Thus: +.DS + if ! [ -d $1 ] + then + echo $1 is not a directory + fi +.DE +will print a message only if $1 is not a directory. .SH 2.8\ Command\ grouping .LP @@ -767,24 +844,44 @@ have the same effect but leave the invoking shell in the directory \fBx.\fP .SH -2.9\ Debugging\ shell\ procedures +2.9\ Shell\ Functions +.LP +A function may be defined by the syntax +.DS + \fIfuncname\fP() \fB{\fI command-list\fB ; }\fR +.DE +Functions are invoked within a script as though they were separate +commands of the same name. +While they are executed, the +positional parameters \fB$1, $2, \*(ZZ\fR are temporarily set to the +arguments passed to the function. For example: +.DS + count() { + echo $2 : $# + } + + count a b c +.DE +would print `b : 3'. +.SH +2.10\ Debugging\ shell\ scripts .LP The shell provides two tracing mechanisms -to help when debugging shell procedures. -The first is invoked within the procedure +to help when debugging shell scripts. +The first is invoked within the script as .DS set \(miv .DE (\fBv\fP for verbose) and causes lines of the -procedure to be printed as they are read. +script to be printed as they are read. It is useful to help isolate syntax errors. -It may be invoked without modifying the procedure +It may be invoked without modifying the script by saying .DS - sh \(miv proc \*(ZZ + sh \(miv \fIscript\fP \*(ZZ .DE -where \fIproc\fP is the name of the shell procedure. +where \fIscript\fP is the name of the shell script. This flag may be used in conjunction with the \fB\(min\fP flag which prevents execution of subsequent commands. @@ -806,12 +903,12 @@ .DS set \(mi .DE -and the current setting of the shell flags is available as \fB$\(mi\|.\fR +and the current setting of the shell flags is available as \fB$\(mi\|\fR. .SH -2.10\ The\ man\ command +2.11\ The\ man\ command .LP -The following is the \fIman\fP command -which is used to diplay sections of the UNIX manual on your terminal. +The following is a simple implementation of the \fIman\fP command, +which is used to display sections of the UNIX manual on your terminal. It is called, for example, as .DS man sh @@ -827,10 +924,12 @@ from section 2, which covers system calls. .sp 2 .DS - cd /usr/man + #!/bin/sh + + cd /usr/share/man - : \'colon is the comment command\' - : \'default is nroff ($N), section 1 ($s)\' + # "#" is the comment character + # default is nroff ($N), section 1 ($s) N=n\ s=1 for i @@ -842,16 +941,20 @@ .sp .5 \*(DC\(min) N=n ;; .sp .5 - \*(DC\(mi\*(ST) echo unknown flag \\\\\'$i\\\\\' ;; + \*(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\*(ST) if [ \(mif man$s/$i.$s ] + \*(DC then + \*(DC ${N}roff \(miman 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 + \*(DC \*(DOif [ \(mif man$j/$i.$j ] + \*(DC \*(DOthen + \*(DC \*(DO\*(THman $j $i \*(DC \*(DO\*(THfound=yes + \*(DC \*(DO\*(THbreak \*(DC \*(DOfi \*(DC done \*(DC case $found in Index: src/bin/sh/USD.doc/t3 diff -u src/bin/sh/USD.doc/t3:1.1 src/bin/sh/USD.doc/t3:1.2 --- src/bin/sh/USD.doc/t3:1.1 Sun Aug 22 01:58:17 2010 +++ src/bin/sh/USD.doc/t3 Sun Aug 22 02:03:06 2010 @@ -42,13 +42,13 @@ .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 +or when a shell script is invoked. +An argument to a command 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. +before execution of the command begins. The value of \fIname\fP in the invoking shell is not affected. For example, @@ -57,64 +57,69 @@ .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 +.\" Removed by Perry Metzger because -k is not in POSIX +.\" +.\" 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. +from within a script. For example, .DS - set\ \(mi\ \*(ST + set\ \(mi\(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 +Note that the first argument, \(mi\(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 +When a command is executed both positional parameters +and shell variables may be set on invocation. +Variables are also made available implicitly +to a command by specifying in advance that such parameters -are to be exported. +are to be exported from the invoking shell. For example, .DS - export\ user\ box + export\ user\ box=red .DE marks the variables \fBuser\fP and \fBbox\fP -for export. -When a shell procedure is invoked +for export (setting \fBbox\fP to ``red'' in the process). +When a command is invoked copies are made of all exportable variables -for use within the invoked procedure. +(also known as \fIenvironment variables\fP) +for use within the invoked program. Modification of such variables -within the procedure does not +within an invoked command does not affect the values in the invoking shell. It is generally true of -a shell procedure +a shell script or other program that it -may not modify the state +cannot modify the state of its caller without explicit -request on the part of the caller. -(Shared file descriptors are an -exception to this rule.) +actions on the part of the caller. +.\" Removed by Perry Metzger because this is confusing to beginners. +.\" +.\" (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 + readonly name[=value] \*(ZZ .DE Subsequent attempts to set readonly variables are illegal. @@ -136,53 +141,56 @@ A default string may be given as in .DS - echo ${d\(mi\fB.\fR} + echo ${d:\(mi\fB.\fR} .DE which will echo the value of the variable \fBd\fP -if it is set and `\fB.\fP' otherwise. +if it is set and not null and `\fB.\fP' otherwise. The default string is evaluated using the usual quoting conventions so that .DS - echo ${d\(mi\'\*(ST\'} + echo ${d:\(mi\'\*(ST\'} .DE will echo \fB\*(ST\fP if the variable \fBd\fP -is not set. +is not set or null. Similarly .DS - echo ${d\(mi$1} + echo ${d:\(mi$1} .DE -will echo the value of \fBd\fP if it is set +will echo the value of \fBd\fP if it is set and not null and the value (if any) of \fB$1\fP otherwise. +.LP +The notation ${d:+\fB.\fR} performs the inverse operation. It +substitutes `\fB.\fP' if \fBd\fP is set or not null, and otherwise +substitutes null. +.LP A variable may be assigned a default value using the notation .DS - echo ${d=\fB.\fR} + echo ${d:=\fB.\fR} .DE which substitutes the same string as .DS - echo ${d\(mi\fB.\fR} + echo ${d:\(mi\fB.\fR} .DE -and if \fBd\fP were not previously set +and if \fBd\fP were not previously set or null 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} + echo ${d:?\fImessage\fP} .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. +will echo the value of the variable \fBd\fP if it is set and not null, +otherwise \fImessage\fP is printed by the shell and +execution of the shell script 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. +A shell script that requires some variables +to be set might start as follows: .DS - :\ ${user?}\ ${acct?}\ ${bin?} + :\ ${user:?}\ ${acct:?}\ ${bin:?} \*(ZZ .DE Colon (\fB:\fP) is a command @@ -191,7 +199,7 @@ 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. +will abandon execution of the script. .SH 3.3\ Command\ substitution .LP @@ -201,31 +209,35 @@ output the name of the current directory. For example, if the current directory is \fB/usr/fred/bin\fR -then the command +then the commands .DS - d=\`pwd\` + d=$(pwd) .DE +(or the older notation d=\`pwd\`) is equivalent to .DS d=/usr/fred/bin .DE .LP -The entire string between grave accents (\`\*(ZZ\`) +The entire string inside $(\*(ZZ)\| (or 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 +(The difference between the $(\*(ZZ) and \`\*(ZZ\` notations is that +the former may be nested, while the latter cannot be.) +.LP +The command is written using the usual quoting conventions, +except that inside \`\*(ZZ\` +a \fB\`\fR must be escaped using +a \fB\\\|\fR. For example, .DS - ls \`echo "$1"\` + ls $(echo "$HOME") .DE is equivalent to .DS - ls $1 + ls $HOME .DE Command substitution occurs in all contexts where parameter substitution occurs (including \fIhere\fP documents) and the @@ -233,7 +245,7 @@ in both cases. This mechanism allows string processing commands to be used within -shell procedures. +shell scripts. An example of such a command is \fIbasename\fP which removes a specified suffix from a string. For example, @@ -246,7 +258,7 @@ .DS case $A in \*(Ca\*(ZZ - \*(Ca\*(ST\fB.\fPc) B=\`basename $A \fB.\fPc\` + \*(Ca\*(ST\fB.\fPc) B=$(basename $A \fB.\fPc) \*(Ca\*(ZZ esac .DE @@ -265,7 +277,7 @@ most recent first. .IP \(bu .ft B -set \`date\`; echo $6 $2 $3, $4 +set \(mi\(mi\| \`date\`; echo $6 $2 $3, $4 .ft R .br will print, e.g., @@ -274,7 +286,24 @@ .ft R .RE .SH -3.4\ Evaluation\ and\ quoting +3.4\ Arithmetic\ Expansion +.LP +Within a $((\*(ZZ)) construct, integer arithmetic operations are +evaluated. +(The $ in front of variable names is optional within $((\*(ZZ)). +For example: +.DS + x=5; y=1 + echo $(($x+3*2)) + echo $((y+=x)) + echo $y +.DE +will print `11', then `6', then `6' again. +Most of the constructs permitted in C arithmetic operations are +permitted though some (like `++') are not universally supported \(em +see the shell manual page for details. +.SH +3.5\ Evaluation\ and\ quoting .LP The shell is a macro processor that provides parameter substitution, command substitution and file @@ -292,7 +321,9 @@ .IP \(bu parameter substitution, e.g. \fB$user\fP .IP \(bu -command substitution, e.g. \fB\`pwd\`\fP +command substitution, e.g. \fB$(pwd)\fP or \fB\`pwd\`\fP +.IP \(bu +arithmetic expansion, e.g. \fB$(($count+1))\fP .RS .LP Only one evaluation occurs so that if, for example, the value of the variable @@ -360,6 +391,7 @@ and may be quoted using \fB\\\|.\fP .DS \fB$ \fPparameter substitution + \fB$()\fP command substitution \fB\`\fP command substitution \fB"\fP ends the quoted string \fB\e\fP quotes the special characters \fB$ \` " \e\fP @@ -434,7 +466,7 @@ executed. For example, .DS - wg=\\'eval who\*(VTgrep\\' + wg=\'eval who\*(VTgrep\' $wg fred .DE is equivalent to @@ -444,10 +476,10 @@ In this example, \fIeval\fP is required since there is no interpretation -of metacharacters, such as \fB\*(VT\|,\fP following +of metacharacters, such as \fB\*(VT\|\fR, following substitution. .SH -3.5\ Error\ handling +3.6\ Error\ handling .LP The treatment of errors detected by the shell depends on the type of error @@ -455,8 +487,11 @@ used interactively. An interactive shell is one whose input and output are connected -to a terminal (as determined by -\fIgtty\fP (2)). +to a terminal. +.\" Removed by Perry Metzger, obsolete and excess detail +.\" +.\" (as determined by +.\" \fIgtty\fP (2)). A shell invoked with the \fB\(mii\fP flag is also interactive. .LP @@ -484,7 +519,7 @@ 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. +to exit from a script. An interactive shell will return to read another command from the terminal. Such errors include the following. @@ -526,8 +561,8 @@ Figure 3. UNIX signals\(dg .ft .FS -\(dg Additional signals have been added in Berkeley Unix. See sigvec(2) or signal(3C) -for an up-to-date list. +\(dg Additional signals have been added in modern Unix. +See \fIsigvec\fP(2) or \fIsignal\fP(3) for an up-to-date list. .FE Those signals marked with an asterisk produce a core dump @@ -538,9 +573,9 @@ The signals in this list of potential interest to shell programs are 1, 2, 3, 14 and 15. .SH -3.6\ Fault\ handling +3.7\ Fault\ handling .LP -Shell procedures normally terminate +shell scripts normally terminate when an interrupt is received from the terminal. The \fItrap\fP command is used @@ -558,11 +593,11 @@ .DE \fIexit\fP is another built-in command -that terminates execution of a shell procedure. +that terminates execution of a shell script. The \fIexit\fP is required; otherwise, after the trap has been taken, the shell will resume executing -the procedure +the script at the place where it was interrupted. .LP UNIX signals can be handled in one of three ways. @@ -575,7 +610,7 @@ 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, +on entry to the shell script, for example, by invoking it in the background (see 3.7) then \fItrap\fP commands (and the signal) are ignored. .LP @@ -584,15 +619,17 @@ command (Figure 4). The cleanup action is to remove the file \fBjunk$$\fR\|. .DS + #!/bin/sh + 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 then cp\ $i\ junk$$;\ mv\ junk$$ $i \*(DC elif\ test\ $flag - \*(DC then echo\ file\ \\\\\'$i\\\\\'\ does\ not\ exist + \*(DC then echo\ file\ \\'$i\\'\ does\ not\ exist \*(DC else >$i \*(DC fi \*(DOesac @@ -615,9 +652,9 @@ 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. +shell script. .LP -A procedure may, itself, elect to +A script may, itself, elect to ignore signals by specifying the null string as the argument to trap. The following fragment is taken from the @@ -627,7 +664,7 @@ .DE which causes \fIhangup, interrupt, quit \fRand\fI kill\fR to be ignored both by the -procedure and by invoked commands. +script and by invoked commands. .LP Traps may be reset by saying .DS @@ -640,7 +677,7 @@ trap .DE .LP -The procedure \fIscan\fP (Figure 5) is an example +The script \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 @@ -677,7 +714,7 @@ an end-of-file is read or an interrupt is received. .SH -3.7\ Command\ execution +3.8\ 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 @@ -764,40 +801,42 @@ (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. +.\" Removed by Perry Metzger, most of this is now obsolete +.\" +.\" .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 +3.9\ Invoking\ the\ shell .LP The following flags are interpreted by the shell when it is invoked. @@ -822,6 +861,84 @@ (so that \fBwait\fP is interruptable). In all cases QUIT is ignored by the shell. .SH +3.10\ Job\ Control +.LP +When a command or pipeline (also known as a \fIjob\fP) is running in +the foreground, entering the stop character (typically +\s-1CONTROL-Z\s0 but user settable with the \fIstty\fP(1) command) +will usually cause the job to stop. +.LP +The jobs associated with the current shell may be listed by entering +the \fIjobs\fP command. +Each job has an associated \fIjob number\fP. +Jobs that are stopped may be continued by entering +.DS + bg %\fIjobnumber\fP +.DE +and jobs may be moved to the foreground by entering +.DS + fg %\fIjobnumber\fP +.DE +If there is a sole job with a particular name (say only one instance +of \fIcc\fP running), \fIfg\fP and \fIbg\fP may also use name of the +command in place of the number, as in: +.DS + bg %cc +.DE +If no `\fB%\fP' clause is entered, most recently stopped job +(indicated with a `+' by the \fIjobs\fP command) will be assumed. +See the manual page for the shell for more details. +.SH +3.11\ Aliases +.LP +The \fIalias\fP command creates a so-called shell alias, which is an +abbreviation that macro-expands at run time into some other command. +For example: +.DS + alias ls="ls -F" +.DE +would cause the command sequence \fBls -F\fP to be executed whenever +the user types \fBls\fP into the shell. +Note that if the user types \fBls -a\fP, the shell will in fact +execute \fBls -F -a\fP. +The command \fBalias\fP on its own prints out all current aliases. +The \fIunalias\fP command, as in: +.DS + unalias ls +.DE +will remove an existing alias. +Aliases can shadow pre-existing commands, as in the example above. +They are typically used to override the interactive behavior of +commands in small ways, for example to always invoke some program with +a favorite option, and are almost never found in scripts. +.SH +3.12\ Command\ Line\ Editing\ and\ Recall +.LP +When working interactively with the shell, it is often tedious to +retype previously entered commands, especially if they are complicated. +The shell therefore maintains a so-called \fIhistory\fP, which is +stored in the file specified by the \fB\s-1HISTFILE\s0\fP environment +variable if it is set. +Users may view, edit, and re-enter previous lines of input using +a small subset of the commands of the \fIvi\fP(1) or +\fIemacs\fP(1)\(dg editors. +.FS +Technically, vi command editing is standardized by POSIX while emacs +is not. +However, all modern shells support both styles. +.FE +Emacs style editing may be selected by entering +.DS + set -o emacs +.DE +and vi style editing may be selected with +.DS + set -o vi +.DE +The details of how command line editing works are beyond the scope of +this document. +See the shell manual page for details. +.SH Acknowledgements .LP The design of the shell is Index: src/bin/sh/USD.doc/t4 diff -u src/bin/sh/USD.doc/t4:1.1 src/bin/sh/USD.doc/t4:1.2 --- src/bin/sh/USD.doc/t4:1.1 Sun Aug 22 01:58:17 2010 +++ src/bin/sh/USD.doc/t4 Sun Aug 22 02:03:06 2010 @@ -41,14 +41,16 @@ .SH Appendix\ A\ -\ Grammar .LP +Note: This grammar needs updating, it is obsolete. +.LP .LD \fIitem: word input-output name = value -.sp 0.8 +.sp 0.7 simple-command: item simple-command item -.sp 0.8 +.sp 0.7 command: simple-command \fB( \fIcommand-list \fB) \fB{ \fIcommand-list \fB} @@ -58,44 +60,44 @@ \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 +.sp 0.7 +\fIpipeline: command pipeline \fB\*(VT\fI command -.sp 0.8 -andor: pipeline +.sp 0.7 +andor: pipeline andor \fB&&\fI pipeline andor \fB\*(VT\*(VT\fI pipeline -.sp 0.8 +.sp 0.7 command-list: andor command-list \fB;\fI command-list \fB&\fI command-list \fB;\fI andor command-list \fB&\fI andor -.sp 0.8 +.sp 0.7 input-output: \fB> \fIfile \fB< \fIfile \fB\*(AP \fIword \fB\*(HE \fIword -.sp 0.8 +.sp 0.7 file: word \fB&\fI digit \fB&\fI \(mi -.sp 0.8 +.sp 0.7 case-part: pattern\fB ) \fIcommand-list\fB ;; -.sp 0.8 -\fIpattern: word +.sp 0.7 +\fIpattern: word pattern \fB\*(VT\fI word -.sp 0.8 +.sp 0.7 \fIelse-part: \fBelif \fIcommand-list\fB then\fI command-list else-part\fP \fBelse \fIcommand-list\fI empty -.sp 0.8 +.sp 0.7 empty: -.sp 0.8 +.sp 0.7 word: \fRa sequence of non-blank characters\fI -.sp 0.8 +.sp 0.7 name: \fRa sequence of letters, digits or underscores starting with a letter\fI -.sp 0.8 +.sp 0.7 digit: \fB0 1 2 3 4 5 6 7 8 9\fP .DE .LP @@ -111,52 +113,56 @@ `andf' symbol .IP \fB\*(VT\*(VT\fR 6 `orf' symbol -.IP \fB;\fP 6 +.IP \fB;\fP 8 command separator -.IP \fB;;\fP 6 +.IP \fB;;\fP 8 case delimiter -.IP \fB&\fP 6 +.IP \fB&\fP 8 background commands -.IP \fB(\ )\fP 6 +.IP \fB(\ )\fP 8 command grouping -.IP \fB<\fP 6 +.IP \fB<\fP 8 input redirection -.IP \fB\*(HE\fP 6 +.IP \fB\*(HE\fP 8 input from a here document -.IP \fB>\fP 6 +.IP \fB>\fP 8 output creation -.IP \fB\*(AP\fP 6 +.IP \fB\*(AP\fP 8 output append .sp 2 .RE .LP b) patterns .RS -.IP \fB\*(ST\fP 6 +.IP \fB\*(ST\fP 8 match any character(s) including none -.IP \fB?\fP 6 +.IP \fB?\fP 8 match any single character -.IP \fB[...]\fP 6 +.IP \fB[...]\fP 8 match any of the enclosed characters .sp 2 .RE .LP c) substitution .RS -.IP \fB${...}\fP 6 +.IP \fB${...}\fP 8 substitute shell variable -.IP \fB\`...\`\fP 6 +.IP \fB$(...)\fP 8 +substitute command output +.IP \fB\`...\`\fP 8 substitute command output +.IP \fB$((...))\fP 8 +substitute arithmetic expression .sp 2 .RE .LP d) quoting .RS -.IP \fB\e\fP 6 +.IP \fB\e\fP 8 quote the next character -.IP \fB\'...\'\fP 6 +.IP \fB\'...\'\fP 8 quote the enclosed characters except for \' -.IP \fB"\&..."\fR 6 +.IP \fB"\&..."\fP 8 quote the enclosed characters except for \fB$ \` \e "\fP .sp 2 @@ -168,6 +174,6 @@ if then else elif fi case in esac for while until do done -{ } +! { } .ft .DE