ICS 54:
Shell Programming I: Brief notes for Chapter 15
Introduction to Shell Programming
We move from considering UNIX shells as an interactive tools
to their capablities as a
scripting (interpreted programming) languages.
For this aspect of UNIX shells, we switch our focus from
the C shell,
csh,
to the Bourne shell,
sh.
Shell programming is easy.
Put the commands you want to execute into a file.
Make the file executable.
Use the file's name as a command.
Example:
% cat > dated.list << EOD
# Comments are nice. This is one
date # and so is the rest of this line
pwd
ls -l
EOD
% chmod +x dated.list
./dated.list
Notes
This assumes we want to use the Bourne shell.
To use any other shell, make the first line of the file
#!full path name of
shell and options Examples:
#!/usr/bin/csh -f #!/usr/bin/sh
It's standard practice and a very good idea to
always always have the first line indicate the shell.
#!/usr/bin/sh
We could have skipped step 2 above (making the file executable)
and explicitly told the shell to start a new shell to run
the commands in the file:
sh dated.list
To run short sequences of commands in their own subshell,
use parentheses. Example:
(date; pwd; ls -l) > my.listing
The Bourne shell also uses "{...}"
for grouping commands in the current shell.
For the Bourne shell, "." (that's right, just
dot) is equivalent to the C shell's "source"
A superb and very important collection of shell programs
can be found at /etc/rc?.d
After a bit of UNIX System Administration, you will not only
appreciate these individually, but find special meaning in
ls -i /etc/rc?.d/* | sort +n
Shell Variables, Revisited
For the Bourne shell (and its immediate relatives)
somename=somev
Defines the variable somename to have the value
somev
$somename
Replace by value of the variable somename:
${somename:-somev}
Replace by value of the variable somename if it is
set; otherwise, use somev
${somename:=somev}
Replace by value of the variable somename if it is
set; otherwise, set it to somev and then use that value.
${somename:?message}
Continue of the value of the variable somename is set;
otherwise, send (the string) message to standard error,
and stop the execution of the shell, returning a value of
false (1) to the parent process. If message is the
empty string (i.e., ${somename:}),
use a standard default error message string.
Example:
#!/bin/sh -x # Show lines as they are executed
# echo.vars -- Basic sh variables
echo "Inititally, X=\"$X\" and Y=\"$Y\""
X=Alpha
echo "X=\"$X\""
echo '${Y:-"Beta"}'=${Y:-"Beta"}
echo "Y=\"$Y\""
echo '${Y:="Gamma"}'=${Y:="Gamma"}
echo "Y=\"$Y\""
Shell Script Parameters
If cmd is a shell script and one executes the command
cmd a1 a2 a3 ... a9 then, within the script defining cmd,
$0
Refers to cmd
$1
Refers to a1
$2
Refers to a2
$3
Refers to a3
...
...
$9
Refers to a9
Examples:
#!/bin/sh
# SN = Switch the Names of 2 files
mv $1 0funnyname.$$
mv $2 $1
mv 0funnyname.$$ $2
########################################################
#!/bin/sh
# echo.args -- sh script echoing its arguments
echo "\n$0 reporting that it has \$# = $# argument(s)"
echo "Arguments (\$*) = $* ====="
shift
echo "After a shift, arguments (\$*) = $* ====="
echo "This has PID (\$\$) = $$\n"
##### Sample Run:
% ./echo.args this is nice
./echo.args reporting that it has $# = 3 argument(s)
Arguments ($*) = one two three =====
After a shift, arguments ($*) = two three =====
This has PID ($$) = 9596
%
The basic output mechanism: Echo/print string.
Special escape sequences in string
have special meanings, such as \c for do not end this line
and \n for start a newline.
Set the arguments $1,
$2,
$3, ..., etc.
from string.
Examples:
#!/bin/sh
# read.set -- read in new arguments
echo "$# arguments = $* ==="
echo "New arguments please: \c"
read in
echo "Input = $in ==="
set $in
echo "$# new argument(s) = $* ==="
##### Sample Run:
% ./read.set what will happen
3 arguments = what will happen ===
New arguments please: let us see what will happen
Input = let us see what will happen ===
6 new argument(s) = let us see what will happen ===
########################################################
#!/bin/sh
# read2in -- read 2 variables
echo "Input please: \c"
read in1 in2
echo "Input1 = $in1 ===\nInput2 = $in2 ==="
##### Sample Run:
% ./read2in
Input please: what do you want
Input1 = what ===
Input2 = do you want ===
Debugging
The -x option to
sh
causes it to
print commands and their arguments as they are executed.