Conditionals: Making Decisions in Scripts
Make your scripts decide things with if, elif, else, the test command and the case statement.
Scripts that decide
A conditional lets a script check something and choose what to do. For example: if a file already exists, do not overwrite it; if a number is too large, print a warning.
The if statement
#!/bin/bash
age=20
if [ $age -ge 18 ]; then
echo "You are an adult"
fi
The parts:
ifstarts the check.[ ... ]is the test. It succeeds (is true) or fails (is false). Spaces inside the brackets are required.thenstarts the block of commands that runs when the test is true.fi("if" backwards) ends the whole statement.
The semicolon before then ends the test line. You can also put then on its own line instead.
Comparing numbers
Inside [ ] Bash uses letters, not symbols, to compare numbers:
-eqequal-nenot equal-gtgreater than-gegreater than or equal-ltless than-leless than or equal
if [ "$count" -gt 10 ]; then
echo "Lots of files"
fi
This test is true when $count is greater than 10.
Comparing text
=equal!=not equal-z "$s"true if the text is empty-n "$s"true if the text is not empty
if [ "$USER" = "root" ]; then
echo "Careful, you are root"
fi
Always put double quotes around variables in tests. If a variable is empty and unquoted, the test loses an argument and fails with a syntax error.
elif and else
score=72
if [ "$score" -ge 90 ]; then
echo "Grade A"
elif [ "$score" -ge 70 ]; then
echo "Grade B"
else
echo "Keep practising"
fi
elif means "else if" and adds another test. else runs when no test matched. The tests are checked from top to bottom, and only the first true block runs. Here the score is 72, so the output is Grade B.
Testing files
Scripts often ask questions about files and folders.
-e pathexists-f pathis a regular file-d pathis a directory-r,-w,-xis readable, writable, executable-s pathexists and is not empty
if [ -f "notes.txt" ]; then
echo "Found it"
else
echo "Missing, creating it"
touch notes.txt
fi
Combining conditions
if [ "$age" -ge 18 ] && [ "$age" -lt 65 ]; then
echo "Working age"
fi
if [ "$day" = "Sat" ] || [ "$day" = "Sun" ]; then
echo "Weekend"
fi
if [ ! -d "$dir" ]; then
echo "Directory does not exist"
fi
&&means and: both tests must be true.||means or: at least one must be true.!means not: it reverses a test.[ ! -d "$dir" ]is true when$diris not a directory.
The [[ ]] form
Bash also has [[ ... ]]. It is a Bash feature that behaves more safely: it handles empty variables without quotes, allows == and && inside the brackets, and supports pattern matching.
if [[ $name == A* ]]; then
echo "Name starts with A"
fi
Use [ ] when a script must work in other shells, and [[ ]] in scripts that only run in Bash.
case: many choices
When you compare one value to many options, case is tidier than a long elif chain.
read -p "Start, stop or restart? " action
case "$action" in
start) echo "Starting..." ;;
stop) echo "Stopping..." ;;
restart) echo "Restarting..." ;;
*) echo "Unknown option: $action" ;;
esac
(read -p asks the user to type something and stores it in the variable. It is covered in a later lesson.)
Each pattern ends with ), each block ends with ;;, the * pattern matches anything not listed above, and esac ("case" backwards) ends the statement.
[$a -eq 1] fails, but [ $a -eq 1 ] works. The [ is actually a command, so it needs spaces around it like any other command.