summaryrefslogtreecommitdiff
path: root/bin/sh/USD.doc/t2
diff options
context:
space:
mode:
authorKiyoshi Aman <kiyoshi.aman+adelie@gmail.com>2019-02-01 22:55:37 +0000
committerKiyoshi Aman <kiyoshi.aman+adelie@gmail.com>2019-02-03 18:22:05 -0600
commit5b57d28ffb6e1ef86b50f7d05d977826eae89bfe (patch)
tree154a22fe556b49e6927197336f8bf91b12eacd5e /bin/sh/USD.doc/t2
downloaduserland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.tar.gz
userland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.tar.bz2
userland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.tar.xz
userland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.zip
initial population
Diffstat (limited to 'bin/sh/USD.doc/t2')
-rw-r--r--bin/sh/USD.doc/t2971
1 files changed, 971 insertions, 0 deletions
diff --git a/bin/sh/USD.doc/t2 b/bin/sh/USD.doc/t2
new file mode 100644
index 0000000..d49747e
--- /dev/null
+++ b/bin/sh/USD.doc/t2
@@ -0,0 +1,971 @@
+.\" $NetBSD: t2,v 1.3 2010/08/22 02:19:07 perry Exp $
+.\"
+.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" Redistributions of source code and documentation must retain the above
+.\" copyright notice, this list of conditions and the following
+.\" disclaimer.
+.\"
+.\" Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgment:
+.\"
+.\" This product includes software developed or owned by Caldera
+.\" International, Inc. Neither the name of Caldera International, Inc.
+.\" nor the names of other contributors may be used to endorse or promote
+.\" products derived from this software without specific prior written
+.\" permission.
+.\"
+.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+.\" OR OTHERWISE) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" @(#)t2 8.1 (Berkeley) 6/8/93
+.\"
+.SH
+2.0\ Shell\ scripts
+.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 \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
+.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 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 to a script
+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.
+(The variable \fB$@\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 scripts is to loop
+through the arguments (\fB$1, $2, \*(ZZ\fR)
+executing commands once for each argument.
+An example of such a script is
+\fItel\fP that searches the file
+\fB/usr/share/telnos\fR
+that contains lines of the form
+.DS
+ \*(ZZ
+ fred mh0123
+ bert mh0789
+ \*(ZZ
+.DE
+The text of \fItel\fP is
+.DS
+ #!/bin/sh
+
+ for i
+ do
+ grep $i /usr/share/telnos
+ done
+.DE
+The command
+.DS
+ tel fred
+.DE
+prints those lines in \fB/usr/share/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 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 script 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 script
+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'end'
+ \*(ZZ
+ end
+.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\(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
+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/spool/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-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
+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.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
+.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
+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
+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 [ $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 [ \(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.)
+.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
+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 [ \(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 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
+of files.
+.DS
+ #!/bin/sh
+
+ flag=
+ for i
+ do case $i in
+ \*(DC\(mic) flag=N ;;
+ \*(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
+ 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
+ cp \*(ZZ; mv \*(ZZ
+.DE
+copy the file and then overwrite it with the copy,
+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.
+.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
+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\ 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 scripts.
+The first is invoked within the script
+as
+.DS
+ set \(miv
+.DE
+(\fBv\fP for verbose) and causes lines of the
+script to be printed as they are read.
+It is useful to help isolate syntax errors.
+It may be invoked without modifying the script
+by saying
+.DS
+ sh \(miv \fIscript\fP \*(ZZ
+.DE
+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.
+(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.11\ The\ man\ command
+.LP
+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
+ man \(mit ed
+ man 2 fork
+.DE
+In the first the manual section for \fIsh\fP
+is displayed..
+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, which covers system calls.
+.sp 2
+.DS
+ #!/bin/sh
+
+ cd /usr/share/man
+
+ # "#" is the comment character
+ # 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 [ \(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
+ \*(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
+ \*(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