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?
Use the case statement for a multiway branch:
1 2 3 4 5 6 7 8 9 10 11 12 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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 |
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 to indicate the statements to execute if no pattern matches.
Instead, use * as the last pattern—since that pattern will match anything.
Placing it last makes it act as the default and match anything that hasn’t already been matched.
An aside to C/C++ and Java programmers: the bash case is similar to the switch statement, and each pattern corresponds to a case.
Notice though, the variable on which you can switch/case is a shell variable (typically a string value) and the cases
are patterns (not just constant values).
The patterns end with a right parenthesis (not a colon).
The equivalent to the break in C/C++ and Java switch statements is, in bash, a double semicolon.
The equivalent to their default keyword is, in bash, the * pattern.
Matches are case-sensitive, but you may use shopt -s nocasematch (available in bash versions 3.1+) to change that.
This option affects case and [[ commands.
We end the case statement with an esac (that’s “c-a-s-e” spelled backwards; “endcase” was too long, we suppose, just like using elif instead of “elseif” to be shorter).