If command
The GNU bash manual has a great description of how the if-command works:
if test-commands; then consequent-commands; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi
This page contains examples of how to use each form of the if command.
Simple conditional
In the simplest form, the if-command conditions the execution of a command on the succesful execution of another:
if command1; then command2; fi
This is just an arguably more readable version of:
command1 && command2
The condition is that the first command returns status code "OK" (0):
if ls ~/.emacs; then cat ~/.emacs; fi
Explicit test conditional
Sometimes, the condition is not just the return code of a command:
if test 1 -ne 2; then echo "1 is not 2" fi
I find the explicit test command very natural to read - the exception being matching strings using [[ string =~ regexp ]] and BASH_REMATCH.
Careful:
- the test command should end with a ";".
- bash will perform all sorts of preprocessing on the "test" arguments. Always quote them, unless you really want this.
[ condition ] and [[ condition ]] Syntax
In my opinion, this syntax is too obscure to be worth the couple of characters saved:
if [ 1 -eq 5 ]; then... if [[ 1 -eq 5 ]]; then...
This is less readable to me than:
if test 1 -eq 5; then...
I always prefer as little special syntax as possible - which is, of course, a matter of personal preference.
Multiple condition "if"
Use elif to treat multiple cases in one if-statement:
if test 1 -eq 2; then echo "first case" elif test 1 -eq 1; then echo "second case" fi
Default case (if condition then ... else ...)
Use else to execute commands only if none of the conditions were satisfied:
if test 1 -eq 2; then echo "condition OK" else echo "condition KO" fi
Testing that multiple expressions are true ("and")
Use && to test that a number of expressions are all true:
[[ "a" =~ a && "b" =~ b && "c" =~ c ]];
Each expression tests that a string matches a regular expression.
If any of the expressions evaluates to false, subsequent expressions are not evaluated:
# outputs nothing false && echo "Hello world!"
Testing that one of multiple expressions is true ("or")
Use || to test that at least one of a number of expressions is true:
[[ "a" =~ a || "b" =~ b || "c" =~ c ]];
If one of the expressions evaluates to true, subsequent expressions are not evaluated:
# outputs nothing true || echo "Hello world!"
Subexpressions
Consider the following expression:
if test -n "$a" && test -n "$b" || test -n "$c" && test -n "$d"; then echo true; fi
Note: test -n "$a" is true if the variable a is not empty.
Question: Which of the variables a, b, c, and d have to be non-empty for the expression to evaluate to true?
Answer: Don't risk putting yourself or your fellow coders in a position where they would have to know the bash rules of precedence well enough to answer this question!
Use parentheses to clarify your intent:
# "and" takes precedence if (test -n "$a" && test -n "$b") || (test -n "$c" && test -n "$d"); then echo true; fi # "or" takes precedence if test -n "$a" && (test -n "$b" || test -n "$c") && test -n "$d"; then echo true; fi
The test Command
The builtin command test provides various checks:
# Does the file/directory exist? if test -e .; then echo "File or directory exists!"; fi if test -f file; then echo "File exists!"; fi if test -s file; then echo "File exists and is not empty!"; fi if test -d directory; then echo "Directory exists!"; fi # Permissions if test -r .; then echo "File exists and is readable!"; fi if test -w .; then echo "File exists and is writable!"; fi if test -x .; then echo "File exists and is executable!"; fi # Variables if test -v PATH; then echo "Shell variable is set!"; fi # String checks if test -z ""; then echo "String is empty!"; fi if test -n "Not empty"; then echo "String is not empty!"; fi if test "A" = "A"; then echo "Strings are equal!"; fi if test "A" == "A"; then echo "Strings are equal!"; fi if test "A" != "B"; then echo "Strings are not equal!"; fi # Arithmetic if test 4 -gt 3; then echo "4 is greater-than 3"; fi if test 2 -lt 3; then echo "2 is less-than 3"; fi if test 2 -eq 2; then echo "2 is equal-to 2"; fi if test 1 -ne 2; then echo "1 is not-equal-to 2"; fi
The bash documentation contains an excellent description of conditional expressions.