1. Branching with if
The if statement has the following syntax:
if commands; then
#commands
#...
elif commands; then
#commands
#...
else
#commands
#...
fi
The elif and else parts are optional. The elif part can be
repeated more than once.
-
Commands (including the scripts and shell functions) return an exit status. By convention, an exit status of zero indicates success and any other value indicates failure.
ls -d /usr/binecho $?ls -d /bin/usrecho $?The builtin commands
trueandfalsedo nothing except returning an exit status:trueecho $?falseecho $? -
The
ifstatement evaluates the success or failure of the commands, based on their exit status:if true; then echo "It's true."; fiif false; then echo "It's true."; fiIf a list of commands follows
if, the last command in the list is evaluated:if false; true; then echo "It's true."; fiif true; false; then echo "It's true."; fi -
The command used most frequently with
ifistest, which performs a variety of checks and comparisons.touch foo.txtif test -e foo.txt; then echo "File exists"; fiif [ -e foo.txt ]; then echo "File exists"; \
else echo "File does not exist"; fiThe command
[is equivalent totest(it requires]as the last argument).rm -f foo.txtif [ -e foo.txt ]; then echo "File exists"; \
else echo "File does not exist"; fi -
Let's see an example script that is testing files:
test-file.sh#!/bin/bash
# test-file: Evaluate the status of a file
FILE=~/.bashrc
if [ -e "$FILE" ]; then
if [ -f "$FILE" ]; then
echo "$FILE is a regular file."
fi
if [ -d "$FILE" ]; then
echo "$FILE is a directory."
fi
if [ -r "$FILE" ]; then
echo "$FILE is readable."
fi
if [ -w "$FILE" ]; then
echo "$FILE is writable."
fi
if [ -x "$FILE" ]; then
echo "$FILE is executable/searchable."
fi
else
echo "$FILE does not exist"
exit 1
fi
exitvim test-file.shNotice that the parameter
$FILEis quoted within the expression. This is not required, but it is a defense against the parameter being empty or containing whitespace.Notice also the
exitcommand at the end. It can optionally take a number as an argument, which becomes the exit status of the script, indicating success or failure. Without an argument, the default is the exit status of the last command executed. If the commandexitis not present at all, the exit status of the script will be the exit status of the last command executed../test-file.shEdit the script, change the variable
FILEand execute it again. You can also try to set it to the name of a directory.Let's do some more testing
sed -i test-file.sh \
-e '/^FILE=/c FILE=./test-file.sh'
head test-file.sh
./test-file.shsed -i test-file.sh \
-e '/^FILE=/c FILE=~/examples/'
head test-file.sh
./test-file.shsed -i test-file.sh \
-e '/^FILE=/c FILE="non existent file"'
head test-file.sh
./test-file.sh -
Let's see a similar example that uses a function instead:
test-file-fun.sh#!/bin/bash
FILE=~/.bashrc
# test-file: Evaluate the status of a file
test_file () {
if [ -e "$FILE" ]; then
if [ -f "$FILE" ]; then
echo "$FILE is a regular file."
fi
if [ -d "$FILE" ]; then
echo "$FILE is a directory."
fi
if [ -r "$FILE" ]; then
echo "$FILE is readable."
fi
if [ -w "$FILE" ]; then
echo "$FILE is writable."
fi
if [ -x "$FILE" ]; then
echo "$FILE is executable/searchable."
fi
else
echo "$FILE does not exist"
return 1
fi
}
test_filevim test-file-fun.shNotice that instead of
exit, a function can usereturnto indicate the exit status of the function../test-file-fun.shLet's do some more testing
sed -i test-file-fun.sh \
-e '/^FILE=/c FILE=./test-file.sh'
grep '^FILE=' test-file-fun.sh
./test-file-fun.shsed -i test-file-fun.sh \
-e '/^FILE=/c FILE=~/examples/'
grep '^FILE=' test-file-fun.sh
./test-file-fun.shsed -i test-file-fun.sh \
-e '/^FILE=/c FILE="non existent file"'
grep '^FILE=' test-file-fun.sh
./test-file-fun.sh -
An example with testing strings:
test-string.sh#!/bin/bash
# test-string: evaluate the value of a string
ANSWER=maybe
if [ -z "$ANSWER" ]; then
echo "There is no answer." >&2
exit 1
fi
if [ "$ANSWER" = "yes" ]; then
echo "The answer is YES."
elif [ "$ANSWER" = "no" ]; then
echo "The answer is NO."
elif [ "$ANSWER" = "maybe" ]; then
echo "The answer is MAYBE."
else
echo "The answer is UNKNOWN."
fivim test-string.shNotice that when there is an error (
ANSWERis empty), we print the error message tostderrby redirecting the output ofecho(>&2). We also return an exit code of 1 byexit 1../test-string.shLet's do some more testing
sed -i test-string.sh -e '/^ANSWER=/c ANSWER=yes'
./test-string.sh
sed -i test-string.sh -e '/^ANSWER=/c ANSWER=no'
./test-string.sh
sed -i test-string.sh -e '/^ANSWER=/c ANSWER=xyz'
./test-string.sh
sed -i test-string.sh -e '/^ANSWER=/c ANSWER='
./test-string.sh -
A similar example with testing integers:
test-integer.sh#!/bin/bash
# test-integer: evaluate the value of an integer.
INT=-5
if [ -z "$INT" ]; then
echo "INT is empty." >&2
exit 1
fi
if [ "$INT" -eq 0 ]; then
echo "INT is zero."
else
if [ "$INT" -lt 0 ]; then
echo "INT is negative."
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd."
fi
fivim test-integer.sh./test-integer.shChange the number that is assigned to
INTand execute it again.More testing
sed -i test-integer.sh -e '/^INT=/c INT=11'
./test-integer.sh
sed -i test-integer.sh -e '/^INT=/c INT='
./test-integer.sh
sed -i test-integer.sh -e '/^INT=/c INT=0'
./test-integer.sh
sed -i test-integer.sh -e '/^INT=/c INT=12'
./test-integer.sh -
For more details about the available tests let's see the help:
help test | lesshelp [type testtype [