In Section 4.5, we discussed the various shells available for Linux, but shells can also be powerful and consummately flexible programming tools. The differences come through most clearly when it comes to writing shell scripts. The Bourne shell and C shell command languages are slightly different, but the distinction is not obvious with most normal interactive use. In fact, many of the distinctions arise only when you attempt to use bizarre, little-known features of either shell, such as word substitution or some of the more oblique parameter expansion functions.
The most notable difference between Bourne and C shells is the form
of the various flow-control structures, including if ...then
and while
loops. In the Bourne
shell, an if ...then
takes the form:
iflist
thencommands
eliflist
thencommands
elsecommands
fi
where list
is just a sequence of commands
to be used as the conditional expression for the
if
and elif
(short for
“else if”) commands. The
conditional is considered to be true if the exit status of the
list
is zero (unlike Boolean expressions
in C, in shell terminology an exit status of zero indicates
successful completion). The commands
enclosed in the conditionals are simply commands to execute if the
appropriate list
is true. The
then
after each list
must be on a new line to distinguish it from the
list
itself; alternately, you can
terminate the list
with a
;
. The same holds true for the
commands
.
An example is:
if [ "$PS1" ]; then PS1="h:w% " fi
This sequence checks to see whether the shell is a login shell (that
is, whether the prompt variable PS1
is set), and
if so, it resets the prompt to h:w%
, which is a
prompt expansion standing for the hostname followed by the current
working directory. For example:
loomer:/home/loomer/mdw%
The [...]
conditional appearing after the
if
is a bash built-in
command, shorthand for test. The
test command and its abbreviated equivalent
provide a convenient mechanism for testing values of shell variables,
string equivalence, and so forth. Instead of using
[...]
, you could call any set of commands after
the if
, as long as the last
command’s exit value indicates the value of the
conditional.
Under tcsh, an if ...then
compound statement looks like the following:
if (expression
) thencommands
else if (expression
) thencommands
elsecommands
endif
The difference here is that the expression
after the if
is an arithmetic or logical
expression evaluated internally by tcsh, while
with bash the conditional expression is a
command, and the expression returns true or false based on the
command’s exit status. Within
bash, using test or
[...]
is similar to an arithmetic expression as
used in tcsh.
With tcsh, however, if you wish to run external
commands within the expression
, you must
enclose the command in braces:
{
command
}.
The equivalent of the previous bash sequence in tcsh is:
if ($?prompt) then set prompt="%m:%/%% " endif
where tcsh’s own prompt special characters have been used. As you can see, tcsh boasts a command syntax similar to the C language, and expressions are arithmetically and logically oriented. In bash, however, almost everything is an actual command, and expressions are evaluated in terms of exit status values. There are analogous features in either shell, but the approach is slightly different.
A similar change exists with the while
loop. In
bash, this takes the form:
whilelist
docommands
done
You can negate the effect by replacing the word
while
with until
. Again,
list
is just a command sequence to be
executed, and the exit status determines the result (zero for success
and nonzero for failure). Under tcsh the loop
looks like this:
while (expression
)commands
end
where expression
is a logical expression
to be evaluated within tcsh.
This example should be enough to get a head start on understanding the overall differences of shell scripts under bash and tcsh. We encourage you to read the bash(1) and tcsh(1) manual pages (although they serve more as a reference than a tutorial) and Info pages, if you have them available. Various books and tutorials on using these two shells are available as well; in fact, any book on shell programming will do, and you can interpolate the advanced features of bash and tcsh into the standard Bourne and C shells using the manual pages. Learning the bash Shell by Cameron Newham and Bill Rosenblatt and Using csh and tcsh by Paul DuBois (both from O’Reilly) are also good investments.