next up previous contents
Next: String Comparisons Up: Bourne Shell Programming Previous: Bourne Shell Programming

Testing and Branching

The power of programming lies in the ability to have the computer make a decision based on one or more choices (either embedded right in the program or provided by the user when the program is executed). This decision-making process is called branching, because of the obvious analog of a tree-branch system. The tool provided by the Bourne shell to build these branching systems is the if:then:else construct, which has the following form:

if statement_A
then
   statement_B
   statement_C
else
   statement_D
fi
statement_E

What happens here is that statement_A (or more correctly condition_A) is attempted. If a true value is returned, statement_B and then statement_C are carried out, followed by statement_E. If a false value is returned from statement_A, statement_D is executed followed by statement_E. The fi statement signals the end of the construct and allows sequential execution of the following commands to resume.

The interesting part of the branching process is how the decision is made. The programmer sets up a test (statement_A above). Statement_A can be a specific condition (is A bigger than B) or it can be an expression. When the shell executes a command or an expression it returns a value (called the exit status); if the command executes without problems, a true value is returned, otherwise a false value is returned. It may seem strange to have a command act as a test condition, but this is actually a very convenient way to handle errors and other conditions. For example a user may want to automatically print a file, and have an error returned if the file does not exist:

if ls plot.ps
then 
   lpr plot.ps
else
   echo "::::  ERROR FILE DOESN'T EXIST  ::::"
fi

If the file does not exist the shell will produce an error message, separate from the message in the echo statement. This error message is what the shell returns automatically if the argument (filename) for the list command does not exist. The stderr can be redirected form the screen to a file which would keep the error messages from coming up on the screen, but it would also leave a file containing the message in the user's account. Unix provides a tool called the null device to handle situations like this. The null device acts like a file that is emptied as soon as anything is placed in it. Any unwanted output can be redirected to the null device and it will then be immediately disposed of. Care must be taken when sending anything to the null device as nothing can be recovered once it has been sent there. The following modification to the line containing the ls command will send stderr to the null device:

if ls plot.ps 2>/dev/null

The above demonstrates how a return value, or exit status, can be used in a test, but what about other types of tests? Suppose two strings are to be compared, and the result of the comparison determines the next step, or if the status of a file determines the branch taken; what then? The Bourne shell comes with two ways to test conditions, the explicit method: the test statement; and the shorthand method: square brackets []gif. The full general test expression works as follows:

$ string1="APPLE"
$ string2="ORANGE"
$ test "$string1" = "$string2"
$ echo $?
1

The 1 that is returned is a false value. In the Bourne shell an exit value of zero is translated as a true value whereas a non-zero value is translated as a false valuegif. It is also important to note that the white space between the = sign and the values on either side are required. In assignment expressions there would be no white space around the equals sign. When used in a decision branch the above example is a lengthy way to get to the result of the test. A more direct test would take the following form:

if [ "APPLE" = "ORANGE" ]
then
  (A)
else
  (B)
fi

where statement(s) B will be executed, as the strings are clearly not equivalent. Again, the white space around the brackets is necessary. This is a much more elegant method of testing and will be the preferred choice for the remainder of this chapter.

The three conditions that will need to be tested are: string comparisons, file status and integer comparisons.


next up previous contents
Next: String Comparisons Up: Bourne Shell Programming Previous: Bourne Shell Programming

Douglas M Gingrich
Mon Apr 27 15:25:49 MDT 1998