Branching Many Ways
Problem
You have a series of comparisons to make, and the if/then/else
is getting pretty long and
repetitive. Isn’t there an easier way?
Solution
Use the case statement for a multiway branch:
case $FN in *.gif) gif2png $FN ;; *.png) pngOK $FN ;; *.jpg) jpg2gif $FN ;; *.tif | *.TIFF) tif2jpg $FN ;; *) printf "File not supported: %s" $FN ;; esac
The equivalent to this using if/then/else statements is:
if [[ $FN == *.gif ]] then gif2png $FN elif [[ $FN == *.png ]] then pngOK $FN elif [[ $FN == *.jpg ]] then jpg2gif $FN elif [[ $FN == *.tif || $FN == *.TIFF ]] then tif2jpg $FN else printf "File not supported: %s" $FN fi
Discussion
The case
statement will expand
the word (including parameter substitution) between the case
and the in
keywords. It will then try to match the
word with the patterns listed in order. This is a very powerful feature
of the shell. It is not just doing simple value comparisons, but string
pattern matches. We have simple patterns in our example: *.gif
matches any character sequence (signified
by the *) that ends with the literal characters .gif
.
Use |, a vertical bar meaning logical OR, to separate different
patterns for which you want to take the same action. In the example
above, if $FN
ends either with
.tif
or .TIFF
then the pattern will match and the
(fictional) tif2jpg command will be
executed.
Use the double semicolon to end the set of statements or else bash will continue executing into the next set of statements.
There is no else
or default
keyword ...
Get bash Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.