








             AAnn IInnttrroodduuccttiioonn ttoo tthhee UUNNIIXX SShheellll


                        _S_. _R_. _B_o_u_r_n_e
                      Murray Hill, NJ

            _(_U_p_d_a_t_e_d _f_o_r _4_._3_B_S_D _b_y _M_a_r_k _S_e_i_d_e_n_)
          _(_F_u_r_t_h_e_r _u_p_d_a_t_e_d _b_y _P_e_r_r_y _E_. _M_e_t_z_g_e_r_)_[_+_]


                          _A_B_S_T_R_A_C_T


     The _s_h_e_l_l is a command programming  language  that
     provides  an  interface  to  the UNIX(R) operating
     system.  Its features include control-flow  primi-
     tives,  parameter  passing,  variables  and string
     substitution.  Constructs such as _w_h_i_l_e_,  _i_f  _t_h_e_n
     _e_l_s_e_,  _c_a_s_e and _f_o_r are available.  Two-way commu-
     nication is possible between the  _s_h_e_l_l  and  com-
     mands.   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.

     The _s_h_e_l_l can modify the environment in which com-
     mands 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.   Com-
     mands can be read either from the terminal or from
     a file, which  allows  command  procedures  to  be
     stored for later use.





-----------
[+] 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).









USD:3-2                    An Introduction to the UNIX Shell


11..00 IInnttrroodduuccttiioonn

The  shell is both a command language and a programming lan-
guage that provides an interface to the UNIX operating  sys-
tem.   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".1 Section 2 describes those features of
the shell primarily intended for  use  within  shell  proce-
dures.    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  fea-
tures  of  the shell.  References of the form "see _p_i_p_e (2)"
are to a section of the UNIX manual.2

11..11 SSiimmppllee ccoommmmaannddss

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,

          who

is  a command that prints the names of users logged in.  The
command

          ls -l

prints a list of files in the current directory.  The  argu-
ment  _-_l  tells _l_s to print status information, size and the
creation date for each file.

11..22 IInnppuutt oouuttppuutt rreeddiirreeccttiioonn

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,

          ls -l >file

The notation _>_f_i_l_e is interpreted by the shell  and  is  not
passed  as  an  argument to _l_s_.  If _f_i_l_e does not exist then
the shell creates it; otherwise  the  original  contents  of
_f_i_l_e  are  replaced  with the output from _l_s_.  Output may be
appended to a file using the notation

          ls -l >>file

In this case _f_i_l_e is also created if  it  does  not  already
exist.










An Introduction to the UNIX Shell                    USD:3-3


The  standard  input  of  a command may be taken from a file
instead of the terminal by writing, for example,

          wc <file

The command _w_c reads its standard input (in this case  redi-
rected from _f_i_l_e) and prints the number of characters, words
and lines found.  If only the number of  lines  is  required
then

          wc -l <file

could be used.

11..33 PPiippeelliinneess aanndd ffiilltteerrss

The  standard  output of one command may be connected to the
standard input of another by writing  the  `pipe'  operator,
indicated by ||, as in,

          ls -l || wc

Two commands connected in this way constitute a _p_i_p_e_l_i_n_e and
the overall effect is the same as

          ls -l >file; wc <file

except that no _f_i_l_e is used.  Instead the two _p_r_o_c_e_s_s_e_s  are
connected  by  a pipe (see _p_i_p_e(2)) and are run in parallel.
Pipes are unidirectional and synchronization is achieved  by
halting _w_c when there is nothing to read and halting _l_s when
the pipe is full.

A _f_i_l_t_e_r is a command that reads its standard input,  trans-
forms  it in some way, and prints the result as output.  One
such filter, _g_r_e_p_, selects from its input those  lines  that
contain some specified string.  For example,

          ls || grep old

prints  those lines, if any, of the output from _l_s that con-
tain the string _o_l_d_.  Another useful filter  is  _s_o_r_t.   For
example,

          who || sort

will print an alphabetically sorted list of logged in users.

A pipeline may consist of more than two commands, for  exam-
ple,

          ls || grep old || wc -l

prints  the  number  of  file names in the current directory









USD:3-4                    An Introduction to the UNIX Shell


containing the string _o_l_d_.

11..44 BBaacckkggrroouunndd ccoommmmaannddss

To execute a command (or pipeline) the shell  normally  cre-
ates the new _p_r_o_c_e_s_s_e_s and waits for them to finish.  A com-
mand may be run without waiting for it to finish.  For exam-
ple,

          cc pgm.c &

calls  the C compiler to compile the file _p_g_m_._c_.  The trail-
ing && 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 _b_a_c_k_g_r_o_u_n_d.   By  contrast,  a  command
executed  without  the  && is said to be running in the _f_o_r_e_-
_g_r_o_u_n_d.[+]

A list of currently active  processes,  including  ones  not
associated with the current shell, may be obtained using the
_p_s(1) command.

11..55 FFiillee nnaammee ggeenneerraattiioonn

Many commands accept arguments which are  file  names.   For
example,

          ls -l main.c

prints information relating to the file _m_a_i_n_._c.

The shell provides a mechanism for generating a list of file
names that match a pattern.  For example,

          ls -l *.c

generates, as arguments to _l_s_, all file names in the current
directory that end in _._c_.  The character * is a pattern that
will match any string including the null string.  In general
_p_a_t_t_e_r_n_s are specified as follows.

     **       Matches  any string of characters including the
             null string.

     ??       Matches any single character.

-----------
[+] Even after execution, one  may  move  commands
from  the  foreground to the background, or tempo-
rarily suspend their execution (which is known  as
_s_t_o_p_p_i_n_g  a  command.  This is described in detail
in section 3.10 on _J_o_b _C_o_n_t_r_o_l..









An Introduction to the UNIX Shell                    USD:3-5


     [[......]]   Matches any one of the characters enclosed.   A
             pair  of  characters  separated by a minus will
             match any character lexically between the pair.

For example,

          [a-z]*

matches  all  names  in the current directory beginning with
one of the letters _a through _z_.

          /usr/fred/test/?

matches all names in the directory //uussrr//ffrreedd//tteesstt that  con-
sist  of  a single character.  If no file name is found that
matches the pattern then the pattern is  passed,  unchanged,
as an argument.

This  mechanism  is useful both to save typing and to select
names according to some pattern.  It may  also  be  used  to
find files.  For example,

          echo /usr/fred/*/core

finds and prints the names of all _c_o_r_e files in sub-directo-
ries of //uussrr//ffrreedd..  (_e_c_h_o is a standard  UNIX  command  that
prints  its arguments, separated by blanks.)  This last fea-
ture can be expensive, requiring a scan of all  sub-directo-
ries of //uussrr//ffrreedd..

There  is  one exception to the general rules given for pat-
terns.  The character `..'  at the start of a file name  must
be explicitly matched.

          echo *

will  therefore echo all file names in the current directory
not beginning with `..'.

          echo ..*

will echo all those file names that begin  with  `..'.   This
avoids inadvertent matching of the names `..' and `....'  which
mean `the current  directory'  and  `the  parent  directory'
respectively.   (Notice  that  _l_s suppresses information for
the files `..' and `....'.)

Finally, the tilde character, `~~', may be used  to  indicate
the home directory of a user.  The `~~' at the beginning of a
path name followed by a non-alphabetic character expands  to
the  current  user's home directory.  If the `~~' is followed
by a login name, it expands to the named user's home  direc-
tory.  For example:










USD:3-6                    An Introduction to the UNIX Shell


          ls ~
          cd ~egbert/

will list the contents of the user's home directory and then
change to the home directory of the user ``egbert''.

11..66 QQuuoottiinngg

Characters that have a special meaning to the shell, such as
<<  >> ** ?? || &&,, are called metacharacters.  A complete list of
metacharacters is given in appendix B.  Any  character  pre-
ceded  by  a  \\  is _q_u_o_t_e_d and loses its special meaning, if
any.  The \\ is elided so that

          echo \?

will echo a single ??,, and

          echo \\

will echo a single \\..  To allow long strings to be continued
over more than one line the sequence \\nneewwlliinnee is ignored.

\\  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,

          echo xx'****'xx

will echo

          xx****xx

The  quoted  string  may  not contain a single quote but may
contain newlines, which are preserved.  This quoting  mecha-
nism is the most simple and is recommended for casual use.

A third quoting mechanism using double quotes is also avail-
able that  prevents  interpretation  of  some  but  not  all
metacharacters.   Discussion  of  the details is deferred to
section 3.5.

11..77 PPrroommppttiinngg

When the shell is used from  a  terminal  it  will  issue  a
prompt  before reading a command.  By default this prompt is
`$$ '.  It may be changed by saying, for example,

          PS1="yesdear$ "

that sets the prompt to be the string _y_e_s_d_e_a_r_$_.  If  a  new-
line  is  typed  and  further input is needed then the shell









An Introduction to the UNIX Shell                    USD:3-7


will issue the prompt `>> '.  Sometimes this can be caused by
mistyping  a  quote mark.  If it is unexpected then entering
the interrupt character (typically  CONTROL-C)  will  return
the  shell  to  read  another  command.   This prompt may be
changed by saying, for example,

          PS2=more

Entering the interrupt character may also be used to  termi-
nate most programs running as the current foreground job.

(PS1 and PS2 are _s_h_e_l_l _v_a_r_i_a_b_l_e_s, which will be described in
section 2.4 below.)

11..88 TThhee sshheellll aanndd llooggiinn

Following _l_o_g_i_n(1) the shell is called to read  and  execute
commands  typed at the terminal.  If the user's login direc-
tory contains the file ..pprrooffiillee then it is assumed  to  con-
tain  commands  and  is read by the shell before reading any
commands from the terminal.

(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 ENV 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.)

11..99 SSuummmmaarryy


     +o    llss
          Print the names of files in the current directory.

     +o    llss >>ffiillee
          Put the output from _l_s into _f_i_l_e_.

     +o    llss || wwcc --ll
          Print  the  number  of files in the current direc-
          tory.

     +o    llss || ggrreepp oolldd
          Print those file names containing the string  _o_l_d_.

     +o    llss || ggrreepp oolldd || wwcc --ll
          Print  the number of files whose name contains the
          string _o_l_d_.

     +o    cccc ppggmm..cc &&
          Run _c_c in the background.













USD:3-8                    An Introduction to the UNIX Shell


22..00 SShheellll ssccrriippttss

The shell may be used to read and execute commands contained
in a file.  For example,

          sh file [ args ...... ]

calls  the shell to read commands from _f_i_l_e_.  Such a file is
called a _s_h_e_l_l _s_c_r_i_p_t_.  Arguments may be supplied  with  the
call and are referred to in _f_i_l_e using the positional param-
eters $$11,, $$22,, ........

For example, if the file _w_g contains

          who || grep $1

then

          sh wg fred

is equivalent to

          who || grep fred


UNIX files have three independent  attributes,  _r_e_a_d_,  _w_r_i_t_e
and  _e_x_e_c_u_t_e_.  The UNIX command _c_h_m_o_d(1) may be used to make
a file executable.  For example,

          chmod +x wg

will ensure that the file _w_g has execute status.   Following
this, the command

          wg fred

is equivalent to

          sh wg fred

This  allows  shell  scripts  and  other programs to be used
interchangeably.  In either case a new process is created to
run the command.

The  `##'  character  is  used  as a comment character by the
shell.  All characters following  the  `#'  on  a  line  are
ignored.

A  typical  modern system has several different shells, some
with differing command syntax, and it is desirable to  spec-
ify which one should be invoked when an executable script is
invoked.  If the special comment











An Introduction to the UNIX Shell                    USD:3-9


          #!/_p_a_t_h/_t_o/_i_n_t_e_r_p_r_e_t_e_r

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,  //bbiinn//sshh  is assumed.)  It is best if a script explic-
itly states what shell it is intended for in this manner.

As well as providing names for  the  positional  parameters,
the number of positional parameters to a script is available
as $$##..  The name of the file being executed is available  as
$$00..

A  special  shell parameter $$** is used to substitute for all
positional parameters except $$00..  A typical use of  this  is
to provide some default arguments, as in,

          nroff -T450 -ms $*

which simply prepends some arguments to those already given.
(The variable $$@@ also expands to  ``all  positional  parame-
ters'', but is subtly different when expanded inside quotes.
See section 3.5, below.)

22..11 CCoonnttrrooll ffllooww -- ffoorr

A frequent use of shell scripts is to loop through the argu-
ments  ($$11,, $$22,, ......)  executing commands once for each argu-
ment.  An example of such a script is _t_e_l that searches  the
file //uussrr//sshhaarree//tteellnnooss that contains lines of the form

          ......
          fred mh0123
          bert mh0789
          ......

The text of _t_e_l is

          #!/bin/sh

          for i
          do
               grep $i /usr/share/telnos
          done

The command

          tel fred

prints  those  lines  in  //uussrr//sshhaarree//tteellnnooss that contain the
string _f_r_e_d_.

          tel fred bert










USD:3-10                   An Introduction to the UNIX Shell


prints those lines containing _f_r_e_d  followed  by  those  for
_b_e_r_t_.

The ffoorr loop notation is recognized by the shell and has the
general form

          ffoorr _n_a_m_e iinn _w_1 _w_2 ......
          ddoo _c_o_m_m_a_n_d_-_l_i_s_t
          ddoonnee

A _c_o_m_m_a_n_d_-_l_i_s_t is a sequence of one or more simple  commands
separated or terminated by a newline or semicolon.  Further-
more, reserved words like ddoo and ddoonnee  are  only  recognized
following  a newline or semicolon.  _n_a_m_e is a shell variable
that is set to the words _w_1 _w_2 ...... in  turn  each  time  the
_c_o_m_m_a_n_d_-_l_i_s_t  following ddoo is executed.  If iinn _w_1 _w_2 ......  is
omitted then the loop is executed once for  each  positional
parameter; that is, iinn _$_* is assumed.

Another  example  of  the  use of the ffoorr loop is the _c_r_e_a_t_e
command whose text is

          for i do >$i; done

The command

          create alpha beta

ensures that two empty files _a_l_p_h_a and _b_e_t_a  exist  and  are
empty.   The notation _>_f_i_l_e may be used on its own to create
or clear the contents of a file.  Notice also that  a  semi-
colon (or newline) is required before ddoonnee..

22..22 CCoonnttrrooll ffllooww -- ccaassee

A  multiple way branch is provided for by the ccaassee notation.
For example,

          case $# in
               1)   cat >>$1 ;;
               2)   cat >>$2 <$1 ;;
               *)   echo 'usage: append [ from ] to' ;;
          esac

is an _a_p_p_e_n_d command.  When called with one argument as

          append file

$$## is the string _1 and the standard input is copied onto the
end of _f_i_l_e using the _c_a_t command.

          append file1 file2

appends  the contents of _f_i_l_e_1 onto _f_i_l_e_2_.  If the number of









An Introduction to the UNIX Shell                   USD:3-11


arguments supplied to _a_p_p_e_n_d is other than 1  or  2  then  a
message is printed indicating proper usage.

The general form of the ccaassee command is

          ccaassee _w_o_r_d iinn
               _p_a_t_t_e_r_n)) _c_o_m_m_a_n_d_-_l_i_s_t;;;;
               ......
          eessaacc

The  shell  attempts to match _w_o_r_d with each _p_a_t_t_e_r_n_, in the
order in which the patterns appear.  If a match is found the
associated  _c_o_m_m_a_n_d_-_l_i_s_t  is  executed  and execution of the
ccaassee is complete.  Since * is the pattern that  matches  any
string it can be used for the default case.

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 * will never be exe-
cuted.

          case $# in
               *) ...... ;;
               *) ...... ;;
          esac


Another  example  of  the use of the ccaassee construction is to
distinguish between different forms  of  an  argument.   The
following example is a fragment of a _c_c command.

          for i
          do case $i in
                  -[ocs])     ...... ;;
                  -*)    echo "unknown flag $i" ;;
                  *.c)   /lib/c0 $i ...... ;;
                  *)     echo "unexpected argument $i" ;;
             esac
          done


To  allow  the same commands to be associated with more than
one pattern the ccaassee command provides for  alternative  pat-
terns separated by a ||.  For example,

          case $i in
               -x||-y)    ......
          esac

is equivalent to












USD:3-12                   An Introduction to the UNIX Shell


          case $i in
               -[xy])    ......
          esac


The usual quoting conventions apply so that

          case $i in
               \?)  ......

will match the character ??..

22..33 HHeerree ddooccuummeennttss

The   shell   script  _t_e_l  in  section  2.1  uses  the  file
//uussrr//sshhaarree//tteellnnooss to supply the data for _g_r_e_p_.  An  alterna-
tive  is  to  include this data within the shell script as a
_h_e_r_e document, as in,

          for i
          do grep $i <<!
             ......
             fred mh0123
             bert mh0789
             ......
          !
          done

In this example the shell takes the lines between <<<<!! and  !!
as  the standard input for _g_r_e_p_.  The string !! is arbitrary,
the document being terminated by a line that consists of the
string following <<.

Parameters are substituted in the document before it is made
available to _g_r_e_p as illustrated  by  the  following  script
called _e_d_g_.

          ed $3 <<%
          g/$1/s//$2/g
          w
          %

The call

          edg string1 string2 file

is then equivalent to the command

          ed file <<%
          g/string1/s//string2/g
          w
          %

and  changes  all occurrences of _s_t_r_i_n_g_1 in _f_i_l_e to _s_t_r_i_n_g_2_.









An Introduction to the UNIX Shell                   USD:3-13


Substitution can be prevented using \ to quote  the  special
character $$ as in

          ed $3 <<+
          1,\$s/$1/$2/g
          w
          +

(This  version of _e_d_g is equivalent to the first except that
_e_d will print a ?? if there are no occurrences of the  string
$$11..)   Substitution  within a _h_e_r_e document may be prevented
entirely by quoting the terminating string, for example,

          grep $i <<'end'
          ......
          end

The document is presented without modification to _g_r_e_p_.   If
parameter  substitution  is  not required in a _h_e_r_e document
this latter form is more efficient.

22..44 SShheellll vvaarriiaabblleess[[++]]

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,

          user=fred box=m000 acct=mh0000

which assigns values to the variables uusseerr,, bbooxx and aacccctt..  A
variable  may be set to the null string by saying, for exam-
ple,

          null=

The value of a variable is substituted by preceding its name
with $$; for example,

          echo $user

will echo _f_r_e_d_.

Variables may be used interactively to provide abbreviations
for frequently used strings.  For example,

          b=/usr/fred/bin
          mv pgm $b

will move the file _p_g_m from the  current  directory  to  the
directory   //uussrr//ffrreedd//bbiinn..    A  more  general  notation  is
-----------
Also known as _e_n_v_i_r_o_n_m_e_n_t _v_a_r_i_a_b_l_e_s,, sseeee  _e_n_v_i_r_o_n_-
_m_e_n_t((77))..









USD:3-14                   An Introduction to the UNIX Shell


available for parameter (or variable) substitution, as in,

          echo ${user}

which is equivalent to

          echo $user

and is used when the parameter name is followed by a  letter
or digit.  For example,

          tmp=/tmp/ps
          ps a >${tmp}a

will direct the output of _p_s to the file //ttmmpp//ppssaa,, whereas,

          ps a >$tmpa

would  cause  the  value  of the variable ttmmppaa to be substi-
tuted.

Except for $$?? the following are set initially by the  shell.
$$?? is set after executing each command.

     $$??      The  exit status (return code) of the last com-
             mand executed as a decimal string.   Most  com-
             mands  return  a  zero exit status if they com-
             plete successfully, otherwise a  non-zero  exit
             status  is  returned.   Testing  the  value  of
             return codes is dealt with later under  iiff  and
             wwhhiillee commands.

     $$##      The  number  of positional parameters (in deci-
             mal).  Used, for example, in the _a_p_p_e_n_d command
             to check the number of parameters.

     $$$$      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,

                       ps a >/tmp/ps$$
                       ......
                       rm /tmp/ps$$


     $$!!      The  process  number of the last process run in
             the background (in decimal).

     $$--      The current shell flags, such as --xx and --vv..

Some variables have a  special  meaning  to  the  shell  and
should be avoided for general use.









An Introduction to the UNIX Shell                   USD:3-15


     $$MMAAIILL   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 _y_o_u _h_a_v_e _m_a_i_l before
             prompting for the next command.  This  variable
             is  typically  set in the file ..pprrooffiillee,, in the
             user's login directory.  For example,

                       MAIL=/usr/spool/mail/fred


     $$HHOOMMEE   The default argument for the _c_d  command.   The
             current  directory is used to resolve file name
             references that do not begin with a //,,  and  is
             changed using the _c_d command.  For example,

                       cd /usr/fred/bin

             makes the current directory //uussrr//ffrreedd//bbiinn..

                       cat wn

             will  print on the terminal the file _w_n in this
             directory.  The command _c_d with no argument  is
             equivalent to

                       cd $HOME

             This  variable is also typically set in the the
             user's login profile.

     $$PPWWDD    The current working directory. Set  by  the  _c_d
             ccoommmmaanndd..

     $$PPAATTHH   A  list  of  directories  that contain commands
             (the _s_e_a_r_c_h _p_a_t_h).  Each time a command is exe-
             cuted  by  the  shell  a list of directories is
             searched for an executable file.  If  $$PPAATTHH  is
             not  set  then the current directory, //bbiinn, and
             //uussrr//bbiinn are searched  by  default.   Otherwise
             $$PPAATTHH  consists of directory names separated by
             ::..  For example,

                       PATH=::/usr/fred/bin::/bin::/usr/bin

             specifies that the current directory (the  null
             string before the first ::), //uussrr//ffrreedd//bbiinn,, //bbiinn
             and //uussrr//bbiinn are to be searched in that  order.
             In this way individual users can have their own
             `private' commands that are accessible indepen-
             dently  of  the current directory.  If the com-
             mand name contains  a  //  then  this  directory
             search is not used; a single attempt is made to









USD:3-16                   An Introduction to the UNIX Shell


             execute the command.

     $$PPSS11    The primary shell prompt  string,  by  default,
             `$$ '.

     $$PPSS22    The  shell prompt when further input is needed,
             by default, `>> '.

     $$IIFFSS    The set of characters used by _b_l_a_n_k _i_n_t_e_r_p_r_e_t_a_-
             _t_i_o_n (see section 3.5).

     $$EENNVV    The  shell  reads  and executes the commands in
             the file specified by this variable when it  is
             initially  started.   Unlike the ..pprrooffiillee 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
             ENV  is not explicitly set. See the manual page
             for your shell.)

22..55 TThhee tteesstt ccoommmmaanndd

The _t_e_s_t  command,  although  not  part  of  the  shell,  is
intended for use by shell programs.  For example,

          test -f file

returns  zero  exit  status if _f_i_l_e exists and non-zero exit
status otherwise.  In general _t_e_s_t evaluates a predicate and
returns  the  result  as  its exit status.  Some of the more
frequently used _t_e_s_t arguments are given here,  see  _t_e_s_t(1)
for a complete specification.

          test s         true if the argument _s is not the null string
          test -f file   true if _f_i_l_e exists
          test -r file   true if _f_i_l_e is readable
          test -w file   true if _f_i_l_e is writable
          test -d file   true if _f_i_l_e is a directory

The _t_e_s_t command is known as `[[' and may be invoked as such.
For aesthetic reasons, the command ignores a  close  bracket
`]]' given at the end of a command so

          [ -f filename ]

and

          test -f filename

are  completely equivalent.  Typically, the bracket notation
is used when _t_e_s_t  is  invoked  inside  shell  control  con-
structs.











An Introduction to the UNIX Shell                   USD:3-17


22..66 CCoonnttrrooll ffllooww -- wwhhiillee

The  actions  of the ffoorr loop and the ccaassee branch are deter-
mined by data available to the shell.  A wwhhiillee or uunnttiill loop
and  an  iiff tthheenn eellssee branch are also provided whose actions
are determined by the exit status returned by  commands.   A
wwhhiillee loop has the general form

          wwhhiillee _c_o_m_m_a_n_d_-_l_i_s_t_1
          ddoo _c_o_m_m_a_n_d_-_l_i_s_t_2
          ddoonnee


The  value tested by the wwhhiillee command is the exit status of
the last simple command following wwhhiillee..   Each  time  round
the loop _c_o_m_m_a_n_d_-_l_i_s_t_1 is executed; if a zero exit status is
returned then _c_o_m_m_a_n_d_-_l_i_s_t_2 is executed; otherwise, the loop
terminates.  For example,

          while [ $1 ]
          do ......
             shift
          done

is equivalent to

          for i
          do ......
          done

_s_h_i_f_t is a shell command that renames the positional parame-
ters $$22,, $$33,, ...... as $$11,, $$22,, ......  and loses $$11..

Another kind of use for the  wwhhiillee//uunnttiill  loop  is  to  wait
until some external event occurs and then run some commands.
In an uunnttiill loop the termination condition is reversed.  For
example,

          until [ -f file ]
          do sleep 300; done
          _c_o_m_m_a_n_d_s

will  loop  until  _f_i_l_e exists.  Each time round the loop it
waits  for  5  minutes  before  trying  again.   (Presumably
another process will eventually create the file.)

The  most recent enclosing loop may be exited with the bbrreeaakk
command, or the rest of the body skipped and the next itera-
tion begun with the ccoonnttiinnuuee command.

The commands _t_r_u_e(1) and _f_a_l_s_e(1) return 0 and non-zero exit
statuses respectively. They are sometimes of use in  control
flow, e.g.:










USD:3-18                   An Introduction to the UNIX Shell


          while true
          do date; sleep 5
          done

is an infinite loop that prints the date and time every five
seconds.

22..77 CCoonnttrrooll ffllooww -- iiff

Also available is a general conditional branch of the form,

          iiff _c_o_m_m_a_n_d_-_l_i_s_t
          tthheenn _c_o_m_m_a_n_d_-_l_i_s_t
          eellssee _c_o_m_m_a_n_d_-_l_i_s_t
          ffii

that tests the value returned by  the  last  simple  command
following iiff..

The iiff command may be used in conjunction with the _t_e_s_t com-
mand to test for the existence of a file as in

          if [ -f file ]
          then _p_r_o_c_e_s_s _f_i_l_e
          else _d_o _s_o_m_e_t_h_i_n_g _e_l_s_e
          fi


An example of the use of iiff,, ccaassee and ffoorr  constructions  is
given in section 2.10.

A multiple test iiff command of the form

          if ......
          then ......
          else if ......
               then ......
               else if ......
                    ......
                    fi
               fi
          fi

may be written using an extension of the iiff notation as,

          if ......
          then ......
          elif ......
          then ......
          elif ......
          ......
          fi











An Introduction to the UNIX Shell                   USD:3-19


The following example is an implementation of the _t_o_u_c_h com-
mand which changes the `last modified' time for  a  list  of
files.   The command may be used in conjunction with _m_a_k_e(1)
to force recompilation of a list of files.

          #!/bin/sh

          flag=
          for i
          do case $i in
                  -c)    flag=N ;;
                  *)     if [ -f $i ]
                    then cp $i junk$$; mv junk$$ $i
                    elif [ $flag ]
                    then echo file \'$i\' does not exist
                    else >$i
                    fi
              esac
          done

The --cc flag is used in  this  command  to  force  subsequent
files  to  be  created if they do not already exist.  Other-
wise, if the file  does  not  exist,  an  error  message  is
printed.   The  shell  variable _f_l_a_g is set to some non-null
string if the --cc argument is encountered.  The commands

          cp ......; mv ......

copy the file and then overwrite  it  with  the  copy,  thus
causing the last modified date to be updated.

The sequence

          if command1
          then command2
          fi

may be written

          command1 && command2

Conversely,

          command1 |||| command2

executes  _c_o_m_m_a_n_d_2 only if _c_o_m_m_a_n_d_1 fails.  In each case the
value returned is that of the last simple command  executed.

Placing  a  `!!' in front of a pipeline inverts its exit sta-
tus, almost in the manner of the  C  operator  of  the  same
name.  Thus:












USD:3-20                   An Introduction to the UNIX Shell


          if ! [ -d $1 ]
          then
               echo $1 is not a directory
          fi

will print a message only if $1 is not a directory.

22..88 CCoommmmaanndd ggrroouuppiinngg

Commands may be grouped in two ways,

          {{ _c_o_m_m_a_n_d_-_l_i_s_t ;; }}

and

          (( _c_o_m_m_a_n_d_-_l_i_s_t ))


In  the  first  _c_o_m_m_a_n_d_-_l_i_s_t is simply executed.  The second
form executes _c_o_m_m_a_n_d_-_l_i_s_t as a separate process.  For exam-
ple,

          (cd x; rm junk )

executes  _r_m  _j_u_n_k  in  the directory xx without changing the
current directory of the invoking shell.

The commands

          cd x; rm junk

have the same effect but leave the  invoking  shell  in  the
directory xx..

22..99 SShheellll FFuunnccttiioonnss

A function may be defined by the syntax

          _f_u_n_c_n_a_m_e() {{ _c_o_m_m_a_n_d_-_l_i_s_t ;; }}

Functions  are  invoked  within a script as though they were
separate commands of the same name.   While  they  are  exe-
cuted, the positional parameters $$11,, $$22,, ...... are temporarily
set to the arguments passed to the function. For example:

          count() {
               echo $2 : $#
          }

          count a b c

would print `b : 3'.











An Introduction to the UNIX Shell                   USD:3-21


22..1100 DDeebbuuggggiinngg sshheellll ssccrriippttss

The shell provides  two  tracing  mechanisms  to  help  when
debugging  shell  scripts.   The first is invoked within the
script as

          set -v

(vv 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

          sh -v _s_c_r_i_p_t ......

where _s_c_r_i_p_t is the name of the shell script.  This flag may
be used in conjunction with the --nn flag which prevents  exe-
cution  of subsequent commands.  (Note that saying _s_e_t _-_n at
a terminal will render the terminal useless until an end-of-
file is typed.)

The command

          set -x

will  produce  an execution trace.  Following parameter sub-
stitution 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

          set -

and the current setting of the shell flags is  available  as
$$--.

22..1111 TThhee mmaann ccoommmmaanndd

The following is a simple implementation of the _m_a_n command,
which is used to display sections of the UNIX manual on your
terminal.  It is called, for example, as

               man sh
               man -t ed
               man 2 fork

In the first the manual section for _s_h is displayed..  Since
no section is specified, section  1  is  used.   The  second
example  will typeset (--tt option) the manual section for _e_d_.
The last prints the _f_o_r_k manual page from section  2,  which
covers system calls.













USD:3-22                   An Introduction to the UNIX Shell


          #!/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
                  [1-9]*)     s=$i ;;
                  -t)    N=t ;;
                  -n)    N=n ;;
                  -*)    echo unknown flag \'$i\' ;;
                  *)     if [ -f man$s/$i.$s ]
                    then
                         ${N}roff -man man$s/$i.$s
                    else # look through all manual sections
                         found=no
                         for j in 1 2 3 4 5 6 7 8 9
                         do
                            if [ -f man$j/$i.$j ]
                            then
                                 man $j $i
                                 found=yes
                                 break
                            fi
                         done
                         case $found in
                              no) echo \'$i: manual page not found\'
                         esac
                    fi
             esac
          done

           FFiigguurree 11.. AA vveerrssiioonn ooff tthhee mmaann ccoommmmaanndd

33..00 KKeeyywwoorrdd ppaarraammeetteerrss

Shell  variables may be given values by assignment or when a
shell script is invoked.  An argument to a  command  of  the
form  _n_a_m_e_=_v_a_l_u_e that precedes the command name causes _v_a_l_u_e
to be assigned to  _n_a_m_e  before  execution  of  the  command
begins.   The  value  of  _n_a_m_e  in the invoking shell is not
affected.  For example,

          user=fred command

will execute _c_o_m_m_a_n_d with uusseerr set to _f_r_e_d.

The _s_e_t command may also be used to set  positional  parame-
ters from within a script.  For example,











An Introduction to the UNIX Shell                   USD:3-23


          set -- *

will set $$11 to the first file name in the current directory,
$$22 to the next, and so on.  Note that  the  first  argument,
--,  ensures  correct  treatment  when  the  first file name
begins with a -.


33..11 PPaarraammeetteerr ttrraannssmmiissssiioonn

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 from the
invoking shell.  For example,

          export user box=red

marks the variables uusseerr and bbooxx for export (setting bbooxx  to
``red''  in  the process).  When a command is invoked copies
are made of all exportable variables (also known as _e_n_v_i_r_o_n_-
_m_e_n_t _v_a_r_i_a_b_l_e_s) for use within the invoked program.  Modifi-
cation of such variables within an invoked command does  not
affect  the  values  in the invoking shell.  It is generally
true of a shell script or other program that it cannot  mod-
ify  the state of its caller without explicit actions on the
part of the caller.

Names whose value is intended  to  remain  constant  may  be
declared  _r_e_a_d_o_n_l_y_.  The form of this command is the same as
that of the _e_x_p_o_r_t command,

          readonly name[=value] ......

Subsequent attempts to set readonly variables are illegal.

33..22 PPaarraammeetteerr ssuubbssttiittuuttiioonn

If a shell parameter is not set then the null string is sub-
stituted for it.  For example, if the variable dd is not set

          echo $d

or

          echo ${d}

will echo nothing.  A default string may be given as in

          echo ${d:-..}

which will echo the value of the variable dd if it is set and
not null and `..' otherwise.  The default string is evaluated
using the usual quoting conventions so that









USD:3-24                   An Introduction to the UNIX Shell


          echo ${d:-'*'}

will echo ** if the variable dd is not set or null.  Similarly

          echo ${d:-$1}

will echo the value of dd if it is set and not null  and  the
value (if any) of $$11 otherwise.

The notation ${d:+..} performs the inverse operation. It sub-
stitutes `..' if dd is set or not null, and otherwise  substi-
tutes null.

A  variable  may be assigned a default value using the nota-
tion

          echo ${d:=..}

which substitutes the same string as

          echo ${d:-..}

and if dd were not previously set or null then it will be set
to the string `..'.

If there is no sensible default then the notation

          echo ${d:?_m_e_s_s_a_g_e}

will  echo  the value of the variable dd if it is set and not
null, otherwise _m_e_s_s_a_g_e is printed by the shell  and  execu-
tion of the shell script is abandoned.  If _m_e_s_s_a_g_e is absent
then a standard message is printed.   A  shell  script  that
requires some variables to be set might start as follows:

          : ${user:?} ${acct:?} ${bin:?}
          ......

Colon  (::)  is  a  command that is built in to the shell and
does nothing once its arguments have been evaluated.  If any
of  the  variables  uusseerr,,  aacccctt  or bbiinn are not set then the
shell will abandon execution of the script.

33..33 CCoommmmaanndd ssuubbssttiittuuttiioonn

The standard output from a command can be substituted  in  a
similar  way  to  parameters.  The command _p_w_d prints on its
standard output the name  of  the  current  directory.   For
example,  if the current directory is //uussrr//ffrreedd//bbiinn then the
commands

          d=$(pwd)

(or the older notation d=`pwd`) is equivalent to









An Introduction to the UNIX Shell                   USD:3-25


          d=/usr/fred/bin


The entire string inside $(......) (or  between  grave  accents
`......`)  is  taken  as  the  command  to  be  executed and is
replaced with the output from the command.  (The  difference
between  the  $(......)  and `......` notations is that the former
may be nested, while the latter cannot be.)

The command is written using the usual quoting  conventions,
except that inside `......` a `` must be escaped using a \\.  For
example,

          ls $(echo "$HOME")

is equivalent to

          ls $HOME

Command substitution occurs in all contexts where  parameter
substitution  occurs  (including  _h_e_r_e  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 scripts.  An example of such a command is _b_a_s_e_-
_n_a_m_e  which  removes  a specified suffix from a string.  For
example,

          basename main..c ..c

will print the string _m_a_i_n_.  Its use is illustrated  by  the
following fragment from a _c_c command.

          case $A in
               ......
               *..c) B=$(basename $A ..c)
               ......
          esac

that sets BB to the part of $$AA with the suffix ..cc stripped.

Here are some composite examples.

     +o    ffoorr ii iinn ``llss --tt``;; ddoo ......
          The  variable  ii  is  set to the names of files in
          time order, most recent first.

     +o    sseett ---- ``ddaattee``;; eecchhoo $$66 $$22 $$33,, $$44
          will print, e.g., _1_9_7_7 _N_o_v _1_, _2_3_:_5_9_:_5_9

33..44 AArriitthhmmeettiicc EExxppaannssiioonn

Within a $((......)) construct, integer  arithmetic  operations
are  evaluated.   (The  $  in  front  of  variable  names is
optional within $((......)).  For example:









USD:3-26                   An Introduction to the UNIX Shell


          x=5; y=1
          echo $(($x+3*2))
          echo $((y+=x))
          echo $y

will print `11', then `6', then `6' again.  Most of the con-
structs  permitted  in C arithmetic operations are permitted
though some (like `++') are not universally supported -- see
the shell manual page for details.

33..55 EEvvaalluuaattiioonn aanndd qquuoottiinngg

The  shell is a macro processor that provides parameter sub-
stitution, 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 var-
ious quoting mechanisms.

Commands are parsed initially according to the grammar given
in appendix A.  Before a command is executed  the  following
substitutions occur.

     +o    parameter substitution, e.g. $$uusseerr

     +o    command substitution, e.g. $$((ppwwdd)) or ``ppwwdd``

     +o    arithmetic expansion, e.g. $$(((($$ccoouunntt++11))))

          Only  one  evaluation occurs so that if, for exam-
          ple, the value of the variable XX is the string  _$_y
          then

                    echo $X

          will echo _$_y_.

     +o    blank interpretation

          Following  the  above  substitutions the resulting
          characters are broken into non-blank words  (_b_l_a_n_k
          _i_n_t_e_r_p_r_e_t_a_t_i_o_n).   For  this  purpose `blanks' are
          the characters of the string  $$IIFFSS.   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,

                    echo ''

          will pass on the null string as the first argument
          to _e_c_h_o, whereas

                    echo $null

          will call _e_c_h_o with no arguments if  the  variable









An Introduction to the UNIX Shell                   USD:3-27


          nnuullll is not set or set to the null string.

     +o    file name generation

          Each  word  is  then  scanned for the file pattern
          characters **,, ?? and  [[......]]   and  an  alphabetical
          list  of  file  names  is generated to replace the
          word.  Each such file name is a separate argument.

The  evaluations  just  described  also occur in the list of
words associated with a ffoorr loop.  Only substitution  occurs
in the _w_o_r_d used for a ccaassee branch.

As  well as the quoting mechanisms described earlier using \\
and ''......'' a third quoting mechanism is provided using double
quotes.   Within double quotes parameter and command substi-
tution occurs but file name generation and  the  interpreta-
tion  of  blanks  does not.  The following characters have a
special meaning within double quotes and may be quoted using
\\..

          $$    parameter substitution
          $$(())  command substitution
          ``    command substitution
          ""    ends the quoted string
          \\    quotes the special characters $$ `` "" \\

For example,

          echo "$x"

will  pass  the value of the variable xx as a single argument
to _e_c_h_o_.  Similarly,

          echo "$*"

will pass the positional parameters as a single argument and
is equivalent to

          echo "$1 $2 ......"

The  notation $$@@ is the same as $$** except when it is quoted.

          echo "$@"

will pass the positional parameters,  unevaluated,  to  _e_c_h_o
and is equivalent to

          echo "$1" "$2" ......


The  following  table gives, for each quoting mechanism, the
shell metacharacters that are evaluated.










USD:3-28                   An Introduction to the UNIX Shell


                          _m_e_t_a_c_h_a_r_a_c_t_e_r
                    \    $    *    `    "    '
               '    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

                  FFiigguurree 22.. QQuuoottiinngg mmeecchhaanniissmmss


In cases where more than  one  evaluation  of  a  string  is
required  the  built-in command _e_v_a_l may be used.  For exam-
ple, if the variable XX has the value _$_y, and if  yy  has  the
value _p_q_r then

          eval echo $X

will echo the string _p_q_r_.

In  general  the _e_v_a_l 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,

          wg='eval who||grep'
          $wg fred

is equivalent to

          who||grep fred

In this example, _e_v_a_l is required since there is  no  inter-
pretation  of metacharacters, such as ||, following substitu-
tion.

33..66 EErrrroorr hhaannddlliinngg

The treatment of errors detected by the shell depends on the
type  of error and on whether the shell is being used inter-
actively.  An interactive shell is one whose input and  out-
put  are  connected to a terminal.  A shell invoked with the
--ii flag is also interactive.

Execution of a command (see also 3.7) may fail  for  any  of
the following reasons.

+o    Input  output  redirection may fail.  For example, if a
     file does not exist or cannot be created.

+o    The command itself does not exist  or  cannot  be  exe-
     cuted.









An Introduction to the UNIX Shell                   USD:3-29


+o    The  command terminates abnormally, for example, with a
     "bus error" or "memory fault".  See Figure 2 below  for
     a complete list of UNIX signals.

+o    The  command terminates normally but returns a non-zero
     exit status.

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 script.  An interactive shell will
return to read another  command  from  the  terminal.   Such
errors include the following.

+o    Syntax errors.  e.g., if ...... then ...... done

+o    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.

+o    Failure of any of the built-in commands such as _c_d_.

The shell flag --ee causes the shell to terminate if any error
is detected.

     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 _k_i_l_l (1))


                 FFiigguurree 33.. UUNNIIXX ssiiggnnaallss[[++]]
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.


-----------
[+] Additional signals have been added  in  modern
Unix.   See  _s_i_g_v_e_c(2)  or _s_i_g_n_a_l(3) for an up-to-
date list.









USD:3-30                   An Introduction to the UNIX Shell


33..77 FFaauulltt hhaannddlliinngg

shell  scripts  normally  terminate  when  an  interrupt  is
received  from  the  terminal.   The _t_r_a_p command is used if
some cleaning up is required,  such  as  removing  temporary
files.  For example,

          trap 'rm /tmp/ps$$; exit' 2

sets  a  trap for signal 2 (terminal interrupt), and if this
signal is received will execute the commands

          rm /tmp/ps$$; exit

_e_x_i_t is another built-in command that  terminates  execution
of  a  shell script.  The _e_x_i_t is required; otherwise, after
the trap has been taken, the shell will resume executing the
script at the place where it was interrupted.

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 script, for example,
by invoking it in the background (see 3.7)  then  _t_r_a_p  com-
mands (and the signal) are ignored.

The  use  of _t_r_a_p is illustrated by this modified version of
the _t_o_u_c_h command (Figure 4).   The  cleanup  action  is  to
remove the file jjuunnkk$$$$.

          #!/bin/sh

          flag=
          trap 'rm -f junk$$; exit' 1 2 3 15
          for i
          do case $i in
                  -c)    flag=N ;;
                  *)     if test -f $i
                    then cp $i junk$$; mv junk$$ $i
                    elif test $flag
                    then echo file \'$i\' does not exist
                    else >$i
                    fi
             esac
          done


                FFiigguurree 44.. TThhee ttoouucchh ccoommmmaanndd

The  _t_r_a_p  command appears before the creation of the tempo-
rary file; otherwise it would be possible for the process to









An Introduction to the UNIX Shell                   USD:3-31


die without removing the file.

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 script.

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 _n_o_h_u_p command.

          trap '' 1 2 3 15

which  causes _h_a_n_g_u_p_, _i_n_t_e_r_r_u_p_t_, _q_u_i_t and _k_i_l_l to be ignored
both by the script and by invoked commands.

Traps may be reset by saying

          trap 2 3

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

          trap


The script _s_c_a_n (Figure 5) is an example of the use of  _t_r_a_p
where there is no exit in the trap command.  _s_c_a_n 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 _s_c_a_n is waiting for input.

          d=`pwd`
          for i in *
          do if test -d $d/$i
             then cd $d/$i
                  while echo "$i:"
                        trap exit 2
                        read x
                  do trap : 2; eval $x; done
             fi
          done


                 FFiigguurree 55.. TThhee ssccaann ccoommmmaanndd

_r_e_a_d _x is a built-in command that reads one  line  from  the
standard  input and places the result in the variable xx..  It
returns a non-zero exit status if either an  end-of-file  is
read or an interrupt is received.











USD:3-32                   An Introduction to the UNIX Shell


33..88 CCoommmmaanndd eexxeeccuuttiioonn

To  run  a  command  (other than a built-in) the shell first
creates a new process using the system call _f_o_r_k_.  The  exe-
cution  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 com-
mand _e_x_e_c is used in the rare cases when no fork is required
and simply replaces the shell with a new command.  For exam-
ple, a simple version of the _n_o_h_u_p command looks like

          trap \'\' 1 2 3 15
          exec $*

The _t_r_a_p turns off the signals specified so  that  they  are
ignored  by  subsequently created commands and _e_x_e_c replaces
the shell by the command specified.

Most forms of input output  redirection  have  already  been
described.  In the following _w_o_r_d is only subject to parame-
ter and command substitution.  No file  name  generation  or
blank interpretation takes place so that, for example,

               echo ...... >*.c

will  write its output into a file whose name is **..cc..  Input
output specifications are evaluated left to  right  as  they
appear in the command.

> _w_o_r_d      The  standard output (file descriptor 1) is sent
            to the file _w_o_r_d which is created if it does not
            already exist.

>> _w_o_r_d     The  standard  output  is sent to file _w_o_r_d_.  If
            the file exists  then  output  is  appended  (by
            seeking  to the end); otherwise the file is cre-
            ated.

< _w_o_r_d      The standard input (file descriptor 0) is  taken
            from the file _w_o_r_d_.

<< _w_o_r_d     The  standard  input  is taken from the lines of
            shell input that follow up to but not  including
            a  line  consisting  only  of  _w_o_r_d_.  If _w_o_r_d is
            quoted then no interpretation  of  the  document
            occurs.   If  _w_o_r_d  is not quoted then parameter
            and command substitution occur and \\ is used  to
            quote the characters \\ $$ `` and the first charac-
            ter of _w_o_r_d_.  In the  latter  case  \\nneewwlliinnee  is
            ignored (c.f. quoted strings).

>& _d_i_g_i_t    The  file  descriptor  _d_i_g_i_t is duplicated using
            the system call _d_u_p (2) and the result  is  used
            as the standard output.









An Introduction to the UNIX Shell                   USD:3-33


<& _d_i_g_i_t    The  standard  input  is  duplicated  from  file
            descriptor _d_i_g_i_t_.

<&-         The standard input is closed.

>&-         The standard output is closed.

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,

          ...... 2>file

runs a command  with  message  output  (file  descriptor  2)
directed to _f_i_l_e_.

          ...... 2>&1

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.)

33..99 IInnvvookkiinngg tthhee sshheellll

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 ..pprrooffiillee..

--cc _s_t_r_i_n_g
     If the --cc flag is present then commands are  read  from
     _s_t_r_i_n_g_.

--ss   If  the  --ss  flag  is present or if no arguments remain
     then commands are read from the standard input.   Shell
     output is written to file descriptor 2.

--ii   If  the  --ii  flag  is present or if the shell input and
     output are attached to a terminal  (as  told  by  _g_t_t_y)
     then this shell is _i_n_t_e_r_a_c_t_i_v_e_.  In this case TERMINATE
     is ignored (so that kkiillll 00 does not kill an interactive
     shell)  and  INTERRUPT  is  caught and ignored (so that
     wwaaiitt is interruptable).  In all cases QUIT  is  ignored
     by the shell.

33..1100 JJoobb CCoonnttrrooll

When  a command or pipeline (also known as a _j_o_b) is running
in the foreground, entering the  stop  character  (typically
CONTROL-Z  but  user settable with the _s_t_t_y(1) command) will
usually cause the job to stop.

The jobs associated with the current shell may be listed  by
entering  the  _j_o_b_s command.  Each job has an associated _j_o_b









USD:3-34                   An Introduction to the UNIX Shell


_n_u_m_b_e_r.  Jobs that are stopped may be continued by entering

          bg %_j_o_b_n_u_m_b_e_r

and jobs may be moved to the foreground by entering

          fg %_j_o_b_n_u_m_b_e_r

If there is a sole job with a particular name (say only  one
instance  of _c_c running), _f_g and _b_g may also use name of the
command in place of the number, as in:

          bg %cc

If no `%%' clause  is  entered,  most  recently  stopped  job
(indicated  with a `+' by the _j_o_b_s command) will be assumed.
See the manual page for the shell for more details.

33..1111 AAlliiaasseess

The _a_l_i_a_s command creates a so-called shell alias, which  is
an  abbreviation  that  macro-expands  at run time into some
other command.  For example:

          alias ls="ls -F"

would cause the command sequence llss --FF to be executed  when-
ever  the  user  types  llss into the shell.  Note that if the
user types llss --aa, the shell will in fact execute llss  --FF  --aa.
The command aalliiaass on its own prints out all current aliases.
The _u_n_a_l_i_a_s command, as in:

          unalias ls

will remove an existing  alias.   Aliases  can  shadow  pre-
existing  commands, as in the example above.  They are typi-
cally 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.

33..1122 CCoommmmaanndd LLiinnee EEddiittiinngg aanndd RReeccaallll

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 _h_i_s_t_o_r_y, which is stored in the file specified by the
HHIISSTTFFIILLEE 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 _v_i(1) or _e_m_a_c_s(1)[+] editors.
-----------
Technically, vi command editing is standardized by
POSIX while emacs is  not.   However,  all  modern
shells support both styles.









An Introduction to the UNIX Shell                   USD:3-35


Emacs style editing may be selected by entering

          set -o emacs

and vi style editing may be selected with

          set -o vi

The details of how command line editing works are beyond the
scope  of  this  document.   See  the  shell manual page for
details.

AAcckknnoowwlleeddggeemmeennttss

The design of the shell is based in  part  on  the  original
UNIX  shell3  and  the PWB/UNIX shell,4 some features having
been taken from both.  Similarities also exist with the com-
mand  interpreters  of the Cambridge Multiple Access System5
and of CTSS.6

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.



RReeffeerreenncceess

1.

2.

3.

4.

5.

6.






















USD:3-36                   An Introduction to the UNIX Shell


AAppppeennddiixx AA -- GGrraammmmaarr

Note: This grammar needs updating, it is obsolete.


_i_t_e_m_:          _w_o_r_d
          _i_n_p_u_t_-_o_u_t_p_u_t
          _n_a_m_e _= _v_a_l_u_e

_s_i_m_p_l_e_-_c_o_m_m_a_n_d_: _i_t_e_m
          _s_i_m_p_l_e_-_c_o_m_m_a_n_d _i_t_e_m

_c_o_m_m_a_n_d_:  _s_i_m_p_l_e_-_c_o_m_m_a_n_d
          (( _c_o_m_m_a_n_d_-_l_i_s_t ))
          {{ _c_o_m_m_a_n_d_-_l_i_s_t }}
          ffoorr _n_a_m_e ddoo _c_o_m_m_a_n_d_-_l_i_s_t ddoonnee
          ffoorr _n_a_m_e iinn _w_o_r_d ...... ddoo _c_o_m_m_a_n_d_-_l_i_s_t ddoonnee
          wwhhiillee _c_o_m_m_a_n_d_-_l_i_s_t ddoo _c_o_m_m_a_n_d_-_l_i_s_t ddoonnee
          uunnttiill _c_o_m_m_a_n_d_-_l_i_s_t ddoo _c_o_m_m_a_n_d_-_l_i_s_t ddoonnee
          ccaassee _w_o_r_d iinn _c_a_s_e_-_p_a_r_t ...... eessaacc
          iiff _c_o_m_m_a_n_d_-_l_i_s_t tthheenn _c_o_m_m_a_n_d_-_l_i_s_t _e_l_s_e_-_p_a_r_t ffii

_p_i_p_e_l_i_n_e_: _c_o_m_m_a_n_d
          _p_i_p_e_l_i_n_e || _c_o_m_m_a_n_d

_a_n_d_o_r_:    _p_i_p_e_l_i_n_e
          _a_n_d_o_r &&&& _p_i_p_e_l_i_n_e
          _a_n_d_o_r |||| _p_i_p_e_l_i_n_e

_c_o_m_m_a_n_d_-_l_i_s_t_:  _a_n_d_o_r
          _c_o_m_m_a_n_d_-_l_i_s_t ;;
          _c_o_m_m_a_n_d_-_l_i_s_t &&
          _c_o_m_m_a_n_d_-_l_i_s_t ;; _a_n_d_o_r
          _c_o_m_m_a_n_d_-_l_i_s_t && _a_n_d_o_r

_i_n_p_u_t_-_o_u_t_p_u_t_:  >> _f_i_l_e
          << _f_i_l_e
          >>>> _w_o_r_d
          <<<< _w_o_r_d

_f_i_l_e_:          _w_o_r_d
          && _d_i_g_i_t
          && _-

_c_a_s_e_-_p_a_r_t_:     _p_a_t_t_e_r_n )) _c_o_m_m_a_n_d_-_l_i_s_t ;;;;

_p_a_t_t_e_r_n_:  _w_o_r_d
          _p_a_t_t_e_r_n || _w_o_r_d

_e_l_s_e_-_p_a_r_t_:     eelliiff _c_o_m_m_a_n_d_-_l_i_s_t tthheenn _c_o_m_m_a_n_d_-_l_i_s_t _e_l_s_e_-_p_a_r_t
          eellssee _c_o_m_m_a_n_d_-_l_i_s_t
          _e_m_p_t_y

_e_m_p_t_y_:









An Introduction to the UNIX Shell                   USD:3-37


_w_o_r_d_:          a sequence of non-blank characters

_n_a_m_e_:          a sequence of letters, digits or underscores starting with a letter

_d_i_g_i_t_:         00 11 22 33 44 55 66 77 88 99


























































USD:3-38                   An Introduction to the UNIX Shell


AAppppeennddiixx BB -- MMeettaa--cchhaarraacctteerrss aanndd RReesseerrvveedd WWoorrddss

a) syntactic

     ||     pipe symbol

     &&&&    `andf' symbol

     ||||    `orf' symbol

     ;;       command separator

     ;;;;      case delimiter

     &&       background commands

     (( ))     command grouping

     <<       input redirection

     <<<<      input from a here document

     >>       output creation

     >>>>      output append



b) patterns

     **       match any character(s) including none

     ??       match any single character

     [[......]]   match any of the enclosed characters



c) substitution

     $${{......}}  substitute shell variable

     $$((......))  substitute command output

     ``......``   substitute command output

     $$((((......))))
             substitute arithmetic expression



d) quoting











An Introduction to the UNIX Shell                   USD:3-39


     \\       quote the next character

     ''......''   quote the enclosed characters except for '

     ""......""   quote the enclosed characters except for $$ ``  \\
             ""



e) reserved words

     iiff tthheenn eellssee eelliiff ffii
     ccaassee iinn eessaacc
     ffoorr wwhhiillee uunnttiill ddoo ddoonnee
     !! {{  }}













































