6.10. Control StructuresTo take advantage of the comparisons described above, you can use various commands that control what command is executed next. While these structures can be used in the interactive Bash shell, they are most often used when writing Bash shell scripts. 6.10.1. case .. in .. esacThe case statement lets you specify multiple actions to be taken when the value of a variable matches one or more values (Figure 6-30).
For example, a section of Bash shell script to print out the home location of the NFL teams listed in our earlier example might look like this: case ${teamname[$index]} in "Dallas Cowboys") echo "Dallas, TX" ;; "Denver Broncos") echo "Denver, CO" ;; "New York Giants"|"New York Jets") echo "New York, NY";; . . . *) echo "Unknown location" ;; esac Note the special use of the pattern "*" as the last pattern. If you go through all the patterns and have never matched anything, this is useful to catch this situation. It is permissible to not match any patterns, in which case, none of the commands will be executed. Here's an example script called "menu.sh" that makes use of a case control structure (this script is also available online; see the Preface for information): #!/bin/bash echo menu test program Here's the output from the "menu.sh" script: $ bash menu.sh menu test program 1 : print the date. 2, 3: print the current working directory. 4 : exit your choice? 1 Thu May 5 07:09:13 CST 2005 1 : print the date. 2, 3: print the current working directory. 4 : exit your choice? 2 6.10.2. if .. then .. elif .. then .. else .. fiThe if statement lets you compare two or more values and branch to a block of commands depending on how the values relate (Figure 6-31).
As an example, let's assume we have a special case for a couple of our NFL teams when printing information about them. We might determine which file of information to print like this: # $index has been set to some arbitrary team in the list # if [ "${teamname[$index]}" == "Minnesota Vikings" ]; then 6.10.3. for .. do .. doneThe for construct is best used when you have a known set of items you wish to iterate over (e.g., a list of hostnames, filenames, or something of that sort) (Figure 6-32). You might use a comparison to jump out of such a loop, or you might simply wish to process each item in the list sequentially.
One example of this use might be if you needed to sort the contents of all text files in a directory: $ ls abc.txt def.txt ghi.txt $ for file in *.txt do sort $file > $file.sorted done $ ls abc.txt def.txt ghi.txt abc.txt.sorted def.txt.sorted ghi.txt.sorted $ _ 6.10.4. while/until .. do .. doneThe while and until constructs work in a similar fashion, performing a loop while or until a test condition is met ("while" in the case that the condition is initially true and you want to loop until it becomes false, "until" in the case that the condition is initially false and you want to loop until it becomes true), as described in Figure 6-33.
These constructs are useful when you don't know exactly when the status of the test condition will be changed. Here's an example of a script that uses an until control structure: $ cat until.sh ...list the script. x=1 until [ $x -gt 3 ] do echo x = $x (( x = $x + 1 )) done $ bash until.sh ...execute the script. x = 1 x = 2 x = 3 $ _ Here's an example of a script that uses a while control structure to generate a small multiplication table: $ cat multi.sh ...list the script. if [ $# -lt 1 ]; then echo "Usage: multi number" exit fi x=1 # set outer loop value while [ $x -le $1 ] # outer loop do 6.10.5. trapThe trap command allows you to specify a command that should be executed when the shell receives a signal of a particular value. Figure 6-34 gives the syntax.
Here's an example of a script that uses the trap control structure. When a Control-C was typed, the shell executed the echo command followed by the exit command: $ cat trap.sh ...list the script. trap 'echo Control-C; exit 1' 2 # trap Ctl-C (signal #2) while test 1 do echo infinite loop sleep 2 # sleep for two seconds. |