Professional Documents
Culture Documents
Bourne Shell
Bourne Shell
Programming
Notes
The Bourne Shell
The Bourne shell is one of
a number of Unix shells (C
shell, Bash shell etc.). Like
the others, it is both a
command language and a
programming language. (A
shell is frequently called a
command interpreter.) As a
command
language
it
provides a user interface to
Unix/Linux. It executes
commands entered by the
user or from a file.
Files containing commands
allow users build their own
commands thus tailoring
the system to their own
needs. Such files are
called: shell scripts, shell
programs, or command
files. These commands
have
access
to
the
command line parameters
and have the same status
as other Unix commands.
As
a
programming
language,
each
shell
provides I/O, variables,
conditionals, loops, and
switches. The syntax is
aimed at ease of use at a
terminal so that strings for
example do not have to be
ShellNotes.JoeCarthy
quoted.
Each
shell
(Bourne, C, Bash etc) has
its own syntax.
Shell
programs
are
typically used to develop:
"User-friendly''
commands
System
administration utilities
Application
utilities
A common criticism of Unix
or the shell in particular, is
that it is unfriendly. Shell
programs can be written to
prompt
the
user
for
parameters, check them
and so on, thus cushioning
the user from the powerful
shell, and making the
system as user-friendly as
required.
Experienced
users often get fed up of
such prompting and usually
prefer using the normal
shell commands.
System administrators can
build shell programs to add
new users, to shutdown the
system and so on. Some
examples are given in
these notes.
Finally useful applications
can be developed with the
shell e.g. a phone lookup
system is briefly described.
The
development
of
applications often requires
ShellNotes.JoeCarthy
Shell Programs
Shell commands may be
stored in a file. There are a
number of ways to execute
the commands in such a
file. One is to use the `sh'
command with the file as a
command line parameter
e.g. prog.sh is a file
containing
3
Unix
commands
Usage:
$ sh prog.sh
Code in prog.sh:
#!/bin/sh
pwd
ls -l
ShellNotes.JoeCarthy
date
Commands
may
be
separated using newlines
as
above
or
using
semicolons:
pwd ; ls -l ; date
Any file name may be
used, the extension `.sh'
has no significance and is
not a Unix convention. The
second and perhaps more
natural way is to use the
`chmod' command to make
the file "executable''. Then
the file name can be
entered directly, just like
any Unix command.
$ chmod +x prog.sh
Make file executable - only
done once
$ prog.sh
Comments
Shell
in
Bourne
ShellNotes.JoeCarthy
mybin=/usr/user/joe/jbin
name=`Bill
Bloggs'
Note that there are no
spaces around the '='
symbol.
Strings containing blanks
or tabs must be quoted.
Input
read
FILENAME
Read is a built-in command
(i.e. part of the shell
program) which reads from
the standard input into the
variable(s) specified. If
more than one variable is
specified, it breaks the
input into words and
assigns each word to the
variables specified. If there
are not enough variables,
ShellNotes.JoeCarthy
read
word2 rest
word1
with input
Output
The echo command is
used to display messages
andthe values of variables.
The program echo simply
prints its command line
parameters
on
the
standard output.
To access the value of a
variable you must precede
the variable name with a
'$' symbol e.g.
echo "Hello
Second Science"
echo
Directory
name
$mybin
is
echo $name
ShellNotes.JoeCarthy
echo
Filename
$FILENAME
is:
echo
-n
"Enter a file name: ''
cp
prog
$mybin
The
shell
simply
substitutes the value of the
variable
for
each
occurrence of the variable
name. So you can use the
variable value as part of a
string:
$
$mybin/prog
ShellNotes.JoeCarthy
ls
-l
prog1.sh
export mybin
mybin=/usr/user/joe/jbin
current=/usr/user/joe
prog2.sh
#
Call
prog2.sh
echo "Back in
prog1.sh''
echo "Value
of mybin'' $mybin
echo "Value
of current'' $current
Program
contains
prog2.sh
echo
"Prog2.sh:
echo "Value
of mybin'' $mybin
echo "Value
of current'' $current
current=/usr/user
mybin=/bin
ShellNotes.JoeCarthy
echo "Value
of mybin'' $mybin
Usage:
$ prog1.sh
Output:
Prog2.sh:
Value
of
mybin /usr/user/joe/jbin
Value
of
Value
mybin /bin
of
Back
in
current
prog1.sh
Value
of
mybin /usr/user/joe/jbin
Value
of
current /usr/user/joe
Exported variables can be
accessed in shell programs
(commands) executed by
this shell.
Note: A shell program
cannot
change
the
environment in which it
was
called.
A
subcommand can change the
value of exported variables
locally, but any changes
made have no effect in the
calling shell. Using export
is similar in effect to 'call by
value' in parameter passing
in C. So prog2.sh can
ShellNotes.JoeCarthy
change
the
variable
"mybin'' locally, but back in
prog1.sh, the value of
"mybin'' is unchanged.
Also, the variable "current''
has no value in prog2.sh,
since it was not marked for
export in prog1.sh.
The
above
are
all
examples of user-defined
variables.
ShellNotes.JoeCarthy
10
date
/tmp/record$$
ps
-a
/tmp/record$$
>
>>
echo $*
Then executing prog.sh:
$
prog.sh
arg1 arg2 word3 abc
ShellNotes.JoeCarthy
11
outputs
arg1
word3 abc
arg2
$ prog word1
word2 word3
Code:
echo $1
shift
echo $1
shift
echo $1
Output:
word1
word2
word3
ShellNotes.JoeCarthy
12
ShellNotes.JoeCarthy
13
echo
echo
$PATH
$HOME
ShellNotes.JoeCarthy
14
Control Flow
The shell provides the
usual
control
flow
mechanisms
associated
with
structured
programming: for, while,
until, case, if-then, and ifthen-else structures.
for var in
word1 word2 word3.......
do
commands
done
Example:
for
screen.c
compare.c
do
i
in
menu.c
echo
"File : " $i
lpr $i
done
ShellNotes.JoeCarthy
15
This
example
simply
displays the name of each
file in the list and sends the
file to the printer. The
commands between 'do'
and 'done' are executed
each time around the loop.
('do' and 'done' delimit the
body of the loop and are
also used in the while and
until structures.)
It is very common to use
the for structure to process
the
command
line
parameters. For example,
to build a create command
which creates empty files,
the file names being
specified on the command
line:
ShellNotes.JoeCarthy
16
Usage:
$ create file1
file2
# Create is a
shell program
#
to
create
files
Code of create:
for File in $*
do
>$File
echo
$File created
done
The notation >filename
causes the shell to create
an empty file or truncate an
existing one.
Because the above loop is
so
common,
an
abbreviated
form
is
available where the "in $*''
is omitted:
for File
do
>$File
echo
$File created
done
ShellNotes.JoeCarthy
17
ShellNotes.JoeCarthy
18
Dept.
Joe
Bloggs
of
Physics
6767
Fred
Smith
5678
Usage:
Dept.
Joe
Bloggs
Of
Physics
6767
Fred
Smith
5678
$
or
$ tel 6767
Output:
ShellNotes.JoeCarthy
19
Dept.
Joe
Bloggs
Of
Physics
6767
$
Code:
# tel program
for i in $*
do
grep i
$i $HOME/phone.dat
done
It simply loops over the
command line arguments
and uses the 'grep'
program to search the file
phone.dat in the user's
home directory.
The i option tells grep to
ignore case i.e. treat
uppercase and lowercase
as the same.
Grep is just one of the
many Unix utilities that
allow you build very
powerful shell programs,
quickly. In fact, to get the
most
out
of
shell
programming, you need to
know what utilities are
available and what they
can do. Important ones are
grep, sort, tr, unique, sed,
ed, and awk.
Remember that the shell
also has the ability to
generate file names using
special characters called
shell metacharacters or
ShellNotes.JoeCarthy
20
wildcard
characters.
(These allow you build
regular expressions for
pattern matching.) The
commonest are * and ?.
The
*
matches
any
sequence of characters,
and on its own the shell will
expand it into the list of
filenames, in alphabetical
order, that are in the
current directory.
Try:
echo *
echo *.c
It is important to realise
that the shell generates
this list of file names before
running
the
echo
command. As far as echo
is concerned, the user may
well have typed the list of
files on the command line.
The ? character matches
any single character.
Ranges of characters may
be specified by enclosing
characters in [] e.g. [A-Z]
specifies any character in
the
range
A to
Z
(uppercase).
This facility to generate
lists of filenames is often
used with the for structure.
For example to print and
then backup all your C
programs:
ShellNotes.JoeCarthy
21
ShellNotes.JoeCarthy
22
Another
example
of
developing a useful utility
using the for structure is a
shutdown procedure to
shutdown the operating
system, but give users a
warning beforehand, so
that they may save their
files and logout:
Usage:
$ shutdown
Code:
for i in 5 4 3 2
1
do
echo
"Going down in $i
minutes'' | /etc/wall
sleep 60
done
/etc/wall <<!
System
Going Down Now
Bye
!
kill -1 1
The program goes around
the for loop 5 times,
sleeping for 60 seconds
during each pass. 'sleep' is
a program that simply
causes your program to be
suspended for the number
of seconds specified i.e. it
does not waste CPU time.
ShellNotes.JoeCarthy
23
24
while
command(s)
do
command(s)
done
The command after "while''
is executed and if it returns
true (exit status 0) then the
ShellNotes.JoeCarthy
25
#asp
program-you could get
bitten for using it !
while true
do
echo
"Sleeping.......
sleep
240
# Sleep for 4
minutes
done
The
program sends a
message to your terminal
every 4 minutes and may
be halted by an interrupt
(Ctrl/C).
Until is the opposite to
while, looping as long as
the condition returns false.
until
false
#
Endless
loop
do
echo
"Sleeping..........''
ShellNotes.JoeCarthy
26
sleep
240
# Sleep for 4
minutes
done
Another example of a
useful
utility
is
the
watchfor program which
waits for a user to login
and writes a message to
his terminal and also echos
a
message
to
your
terminal:
Usage:
watchfor
tom
tom
has
logged on
Code:
Watchfor
program
until
who
grep $1
do
120
2 mins
sleep
# check every
done
# User has
logged on
write $1 <<!
Hello $1, Can
you contact me
!
ShellNotes.JoeCarthy
27
echo $1 "has
logged on''
The pipeline " who | grep
$1 '' causes the output of
the who command to
become the input for grep,
which searches it for the
specified user e.g. tom in
this example.
If grep succeeds in finding
tom in the input, then it
returns an exit status of 0,
which terminates the until
loop. The 'write' command
is used to send a message
to a user's terminal. A "here
document'' is used to
provide the input for 'write'.
In this example, we sleep
for 120 seconds if the user
has not logged on before
going around the loop
again.
ShellNotes.JoeCarthy
28
test
expression
test exp1 -o
exp2
test exp1 -a
exp2
It returns 0 if expression
evaluates to true, non-zero
otherwise. The "-o'' is used
for
to
combine
two
expressions with logical
OR, "-a'' for logical AND.
Examples:
test
-s
File
True if File exists
and is non-empty
test -f File True if
File exists and is not a
directory
ShellNotes.JoeCarthy
29
test -r FileTrue if
File is readable (also -w
for writeable)
test
True
directory
-d
if
File
File is
if
test
-n
Str
True if Str has
non-zero length
test str1 = str2
True if strings are
equal
test n1 -eq
True if n1,
algebraically equal
n2
n2
(Also
-ne, -gt, -e,
-le, -lt for not
equals, etc. )
You can invert the above
conditions by using ! e.g.
test
!
-d
true if file is not a
directory.
ShellNotes.JoeCarthy
30
Sample Usage:
while
test
/tmp/lockfile
do
sleep 5
done
-r
Usage:
$
myprint
file.c file2.c
Code:
# myprint
while test -r
/tmp/lockfile
# Wait
until printer free
do
sleep 5
done
>/tmp/lockfile
# Lock printer
for i in $*
do
pr
$i
> /dev/lp # pr file on
print device
done
ShellNotes.JoeCarthy
31
rm
/tmp/lockfile
printer
Free
ShellNotes.JoeCarthy
32
The
Structure
if-then-fi
conditional-
command
then
commands
fi
if
conditional-
command
then
commands
else
commands
fi
if
conditional-
command
then
commands
elif conditionalcommand
then
commands
else
commands
fi
Example 1
if test $# = 0
then
ShellNotes.JoeCarthy
33
"Usage:
username''
echo
watchfor
exit
fi
Here we check if no
command line parameter is
entered, displaying an error
message if this is so. This
check should be included
at the start of the
"watchfor'' program shown
earlier.
.
ShellNotes.JoeCarthy
34
Example 2
if test $# -ne
2
then
"Invalid 2
expected''
echo
arguments
exit
else
echo " 2
parameters entered''
fi
It is often used to test
conditions about files. We
could use it to modify the
create program developed
earlier, so that it does not
truncate existing files:
# safecreate
program
for i in $*
do
if test -f $i
then
echo $i
"already exists''
else
>$i
done
This program loops over
the
command
line
parameters, testing if each
one exists, creating a file if
it does not already exist.
ShellNotes.JoeCarthy
35
We could make
the
program
interactive,
prompting the user if the
file already exists, to find
out if he wishes to truncate
it:
ShellNotes.JoeCarthy
36
# safecreate2
program
for i in $*
do
if test -f
$i
then
echo
"already exists''
$i
echo
"Truncate it (Y|N)''
-n
read ANS
if
test $ANS = Y -o $ANS
=y
then
>$i
elif
test $ANS = N -o $ANS
=n
then
continue #
Go around loop again
else
echo "Enter Y
or N''
ShellNotes.JoeCarthy
37
safecreate2
$i
fi
else
>$i
fi
done
Here, we show the use of
elif, an abbreviation of else
if. You may have as many
elifs as required.
The continue statement,
takes you to the loop test
again (as in C), enabling
you go around the loop
again.
Finally,
this
program
illustrates a very important
feature, the ability to use a
shell program recursively.
Here if the file already
exists we ask the user for Y
or N reply as to whether to
truncate it. If the user does
not enter one of these
characters then we simply
let the program call itself
with the current file as its
command line parameter.
Since the file already
exists, it will again prompt
the user for a Y or N reply
and proceed accordingly.
This is a useful way of
handling such an error
condition.
ShellNotes.JoeCarthy
38
$
directory-name
lsdir
Example:
$
/usr/user/year3
lsdir
Code:
lsdir
program
PATH=/bin:/usr/bin:/use
r/usr/joe/bin
if test $# = 0
then
lsdir
.
#
Use
current directory
elif test ! -d
$1
# Check
if $1 is a directory
ShellNotes.JoeCarthy
39
then
echo $1
"Not a directory''
ls -l $1
#
List
the file
exit
else
for i in
$1/*
# Loop over
files in $1
do
if
test -d $i # If it is a
directory
then
echo
"Directory: '' $i
( cd $i ; lsdir .
)
else
ls -l $i
ordinary file
\#
fi
done
fi
If no arguments are
supplied to lsdir, it lists the
current directory by calling
itself
recursively
with
parameter ".''. The for
structure, takes the first
parameter, expands it to a
ShellNotes.JoeCarthy
40
ShellNotes.JoeCarthy
41
ShellNotes.JoeCarthy
42
PATH=/bin:/usr/bin
monlist=/tmp/monlist
if test ! -r
$monlist
then
>$monlist
fi
while :
do
date >>
$monlist
echo " ''
>> $monlist
who >>
$monlist
echo " ''
>> $monlist
ps -a >>
$monlist
echo " ''
>> $monlist
sleep
# 5
300
minutes
done
ShellNotes.JoeCarthy
43
ShellNotes.JoeCarthy
44
case word in
pattern1)
command(s) ;;
pattern2)
command(s) ;;
esac
Note
the
double
semicolons terminating
each case.
case $# in
0) Echo
"No
arguments
supplied'' ; exit ;;
2) Echo
"Correct '' ;;
*) Echo
"Incorrect number of
arguments'' ;;
esac
ShellNotes.JoeCarthy
45
Example 2:
command
An append
case $# in
1)
cat
>> $1 ;;
2)
cat
>> $2 < $1 ;;
*) echo
'Usage: append [fromfile] to-file' ;;
esac
Usage:
$
append
thisfile ontothatfile
case $1 in
-o) echo
"-o option entered'' ;;
-c) echo
"-c option entered'' ;;
esac
A range of characters may
be enclosed in []
ShellNotes.JoeCarthy
46
# safecreate3
program using case
for i in $*
do
if test -f
$i
then
echo
"already exists''
$i
echo
"Truncate it (Y|N) ''
-n
read ANS
case $ANS in
y|Y) >$i ;;
n|N) continue
;;
\# Go around
loop again
ShellNotes.JoeCarthy
47
*)
"Enter Y or N''
echo
safecreate3
$i ;;
esac
else
>$i
fi
done
Now that all the control
structures
have
been
discussed, we can see an
example using them all,
enabling us to build a
useful utility program tidy.
This program is used to to
allow you to perform a
number of operations on a
set of files e.g. all files in
your directory. It displays a
menu,
displays
each
filename in turn, reads a
user option allowing the
user to process the file.
Options include display file
contents, list file, print it,
delete it, skip to next file.
As many options as
required may be carried
out on any file.
Usage:
$ tidy *
ShellNotes.JoeCarthy
48
Code:
# Tidy program
if test $# -eq 0
then
echo
"No
files specified"
exit
fi
# Display menu
cat <<!
Exit
x
Next file
n
Display file
t
Delete file
d
List file
l
Print file
p
!
# Process command line
parameters
for i in $*
do
echo "File : ''
$i
# Display file
name
FIN=n
# Process each
file
while test
$FIN = n
do
echo -n "Enter
command: ''
ShellNotes.JoeCarthy
49
read COM
case $COM in
n|N) break ;;
x|X) exit ;;
t|T) cat $i ;;
p|P) lp $i ;;
d|D) rm -i $i ;;
l|L) ls -l $i ;;
*)
"Unknown
$COM'';;
echo
command
esac
echo
echo
-n
"Finished this file (y/n) ''
read FIN #
Only n is checked
done
#
Next
command for this file
done
# Next file
ShellNotes.JoeCarthy
50
Command
Substitution
This is a very powerful
mechanism allowing the
output of a command to be
used inline e.g.
ShellNotes.JoeCarthy
51
today='date'
current='pwd'
Note that the quotes are
grave quotes (') and not
the usual single quotes
(').
The variable today gets as
value the string output by
the 'date' command and
current the output of the
'pwd' command. So
echo $today
echo
are in $current''
"You
echo
are in 'pwd' ''
"You
yields:
Mon Apr
10:20:45 GMT 1996
You
/usr/user/joe
are
in
You
/usr/user/joe
are
in
Command
substitution
allows you build some very
useful programs. Suppose
you wish to mail a group of
users a particular message
then if you create a file of
user names called namelist:
ShellNotes.JoeCarthy
52
joe
tom
year2
year3
..
..
one method of doing it is:
mail
'cat
name-list' < message
The shell executes the
command "cat name-list''
and the output is produced
inline just as if you entered:
year2
message
mail
name-list' <<!
This
'cat
is
the
text
of
the
message
.......
!
If you want to loop over the
files in a directory, in order
ShellNotes.JoeCarthy
53
$ expr 2 + 2
4
By executing the command
inline, we can perform
arithmetic
on
shell
variables. This can be used
to loop over command a
specific number of times.
For example, we could
rewrite
the
shutdown
command
presented
earlier, to use $1 as the
number of minutes until
shutdown time. If no
command line parameters
are specified then 5 is
chosen as the default
ShellNotes.JoeCarthy
54
$ shutdown2
10
#
Shut
system down in 10 mins
ShellNotes.JoeCarthy
55
Code:
#shutdown2
program
if test $# = 0
then
count=5
#
Default is 5 minutes
else
count=$1
fi
i=1
tleft=$count
while test $i -le
$count
do
echo "System
going down in $tleft
minutes'' | /etc/wall
i='expr $i + 1'
# increment i
tleft='expr $tleft
- 1'
sleep 60
done
echo
"System
going down now !!!!!''
| /etc/wall
kill -1 1
Output:
System
going
down in 10 minutes
System
going
down in 9 minutes
....
ShellNotes.JoeCarthy
56
System
going
down in 1 minutes
System
going
down now !!!!!
$
Count gets the value of $1
( a string ), i gets the value
1, and tleft the value of
count for the time left.
Output
of
the
'expr'
command overwrites the
values of i and tleft each
time around the loop, until i
reaches the value of count.
The 'expr' program is not
special, we could use this
method
with
any
C
program
to
perform
whatever operations are
required, although you will
normally find a suitable
utility is available for
whatever you want to do.
Quoting If you want to use
shell metacharacters such
as *, ?, $ as ordinary
characters you must quote
them. There are 3 methods
of quoting in the shell.
1)
The
\
character
quotes the the
next character
e.g.
echo The
star
character: \*
ShellNotes.JoeCarthy
57
echo The
backslash
character: \\
yields
The star
character: *
The
backslash
character: \
2)
Single
quotes ' ' are
used to quote a
group
of
characters:
echo
'***** Warning
**** ???? '
displays
*****
Warning
**** ????
3)
Double
quotes are also
used but only
quote
file
generation
characters
*
and ? e.g.
echo
''$HOME
has
no
filenames
with a * in
them''
displays
ShellNotes.JoeCarthy
58
/usr/user/j
oe
has
no
filenames with
a * in them
Variable and parameter
substitution are carried out
inside double quotes, no
substitutions are performed
inside single quotes.
Here Documents
We have already seen the
use of "here documents''.
One very common use is to
prepare edit scripts for the
ed editor. Instead of using
ed interactively, it can be
used
by
placing
ed
commands in a file and
redirecting the input to
come from the file or from
a here document:
ed file.txt < ed-script
where ed-script contains
editor commands. This is
useful where the same
commands have to be
applied to a number of
files:
ed file.* <<!
1,\$s/Unix/UNIX/
g
a
ShellNotes.JoeCarthy
59
60
ed file <<!
1,\$s/\^Mr/Mister/
g/Jones/d
g/\^$/d
w
q
!
The g command instructs
ed
to
perform
the
command on all lines,
the /Jones/ locates line
with the string "Jones''. See
the ed manual for details.
Note that the caret has to
be quoted since otherwise
it will be interpreted as a
shell
metacharacter
(alternative symbol for
pipe) instead of being
passed to ed. This is a
good example of where
knowledge of a Unix utility,
ed in this case, can save a
lot of work. It is almost
always quicker to learn
how to use existing utilities
to do a job, than to write
even a simple C program
from scratch.
This mechanism can be
used to build a system
utility to add a user to the
ShellNotes.JoeCarthy
61
gid:
group id number
62
ShellNotes.JoeCarthy
63
to
ed /etc/passwd <<!
.a
$1::$2::10::/usr/us
er/$1:/bin/sh
.
w
q
!
mkdir /usr/user/$1
chown
$1
/usr/user/$1
chgrp
user
/user/usr/$1
chmod
go-w
/usr/user/$1
This is a useful command
especially
since
the
password file entry is
ShellNotes.JoeCarthy
64
Signal Handling
In Unix, programs are sent
signals by the kernel in the
event of a program error,
(such as divide by zero, or
memory addressing error)
or when the user hits the
interrupt key (CTRL C), the
quit key (CTRL \), logs out
(Hangs up) or the user
generates a signal with the
'kill' command.
When a program receives
any signal, the default
action is to terminate,
which is usually desirable.
However, there are times
when, control should be
returned to the program,
where appropriate action
can be taken for a given
signal. This allows the
program delete temporary
files before termination, or
the program may be
restarted at a suitable
point, or finally the signal
may be ignored and the
program continues running.
For this reason, the shell
allows the user to "trap''
signals
and
take
ShellNotes.JoeCarthy
65
Hangup
logout
Interrupt
Ctrl/C
Quit Ctrl \
9
-9 pid
(sure) kill
10
Bus
Memory
addressing error
kill
error
15
Software
termination kill -15 pid
The trap command allows
the user trap the signal
ignore it or take action:
trap 'rm /tmp/lockfile ; exit'
1 2 3 15
In the 'lpr' command we
created a lock file to
prevent concurrent access
to the printer. However, if
the
lpr
command
is
interrupted, the lock file will
not be deleted, and the
ShellNotes.JoeCarthy
66
rm /etc/lockfile ; exit
thus freeing the printer and
terminating lpr. This line
should be inserted at the
start of the lpr program.
Signals can be ignored by:
trap '' 1 2 3
trap 1 2 3
As an exercise you could
rewrite the 'asp' program,
to read a user code-word,
go into the sleep loop as
before,
and
when
interrupted, prompt for the
code-word terminating if it
matches that previously
entered,
otherwise
returning to the sleep loop.
Efficiency
of
Shell
Programs
The efficiency of shell
programs can be improved
in a number of ways. By
setting the value of PATH
so that the shell only
searches the necessary
ShellNotes.JoeCarthy
67
for i in $*
do
cat $i
done
cat $*
When you use a shell loop,
then the shell must locate
and load the program each
time around the loop.
When you write 'cat $*' the
'cat' program is only loaded
once, and it performs the
argument processing (after
the shell has expanded $*).
The use of a "here
document'' instead of a
series of 'echo' commands
is also worthwhile.
Exec
and
Commands
ShellNotes.JoeCarthy
(dot)
68
ShellNotes.JoeCarthy
69
'newprog'
terminates,
control returns to the
calling
program.
This
allows the new program to
change variables in the
current shell. This is why
the login command file is
called
'.profile',
it
is
executed as part of the
user's
shell
so
that
variables that are set in
'.profile' remain set when
'.profile' terminates.
Debugging
Shell
Programs
Finally, when debugging
shell programs, you can
invoke them "verbosely''
with
sh -v prog
which causes the program
lines to be printed as they
are being read. This is
useful for finding syntax
errors. You can achieve the
same effect by by entering
set -v
in your program. You can
use
set -n
if you want to switch
execution off, to test the
procedure without running
it.
set -x
ShellNotes.JoeCarthy
70
provides
an
execution
trace. All flags may be
turned off by: set -
ShellNotes.JoeCarthy
71