The "and list" and "or list" constructs provide a means of processing a number of commands consecutively. These can effectively replace complex nested if/then or even case statements.
command-1 && command-2 && command-3 && ... command-n |
Example 25-1. Using an "and list" to test for command-line arguments
#!/bin/bash # "and list" if [ ! -z "$1" ] && echo "Argument #1 = $1" && [ ! -z "$2" ] && echo "Argument #2 = $2" then echo "At least 2 arguments passed to script." # All the chained commands return true. else echo "Less than 2 arguments passed to script." # At least one of the chained commands returns false. fi # Note that "if [ ! -z $1 ]" works, but its supposed equivalent, # if [ -n $1 ] does not. However, quoting fixes this. # if [ -n "$1" ] works. Careful! # It is best to always quote tested variables. # This accomplishes the same thing, using "pure" if/then statements. if [ ! -z "$1" ] then echo "Argument #1 = $1" fi if [ ! -z "$2" ] then echo "Argument #2 = $2" echo "At least 2 arguments passed to script." else echo "Less than 2 arguments passed to script." fi # It's longer and less elegant than using an "and list". exit 0 |
Example 25-2. Another command-line arg test using an "and list"
#!/bin/bash ARGS=1 # Number of arguments expected. E_BADARGS=65 # Exit value if incorrect number of args passed. test $# -ne $ARGS && echo "Usage: `basename $0` $ARGS argument(s)" && exit $E_BADARGS # If condition-1 true (wrong number of args passed to script), # then the rest of the line executes, and script terminates. # Line below executes only if the above test fails. echo "Correct number of arguments passed to this script." exit 0 # To check exit value, do a "echo $?" after script termination. |
Of course, an and list can also set variables to a default value.
arg1=$@ # Set $arg1 to command line arguments, if any. [ -z "$arg1" ] && arg1=DEFAULT # Set to DEFAULT if not specified on command line. |
command-1 || command-2 || command-3 || ... command-n |
Example 25-3. Using "or lists" in combination with an "and list"
#!/bin/bash # delete.sh, not-so-cunning file deletion utility. # Usage: delete filename E_BADARGS=65 if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit $E_BADARGS # No arg? Bail out. else file=$1 # Set filename. fi [ ! -f "$file" ] && echo "File \"$file\" not found. \ Cowardly refusing to delete a nonexistent file." # AND LIST, to give error message if file not present. # Note echo message continued on to a second line with an escape. [ ! -f "$file" ] || (rm -f $file; echo "File \"$file\" deleted.") # OR LIST, to delete file if present. # ( command1 ; command2 ) is, in effect, an AND LIST variant. # Note logic inversion above. # AND LIST executes on true, OR LIST on false. exit 0 |
If the first command in an "or list" returns true, it will execute. |
The exit status of an and list or an or list is the exit status of the last command executed. |
Clever combinations of "and" and "or" lists are possible, but the logic may easily become convoluted and require extensive debugging.
false && true || echo false # false # Same result as ( false && true ) || echo false # false # But *not* false && ( true || echo false ) # (nothing echoed) # Note left-to-right grouping and evaluation of statements, # since the logic operators "&&" and "||" have equal precedence. # It's best to avoid such complexities, unless you know what you're doing. # Thanks, S.C. |
See Example A-8 for an illustration of using an and / or list to test variables.