Make decisions in Bash: if/elif/else, the [[ ]] test command, numeric and string comparisons, file tests, combining conditions, and matching many values with case.
Why: an if statement runs a block only when a test succeeds. The test goes in [[ ]], and the then/fi keywords bracket the body. Note: the spaces inside [[ ... ]] are required — [[a]] is a syntax error.
#!/usr/bin/env bash
score=72
if [[ "$score" -ge 90 ]]; then
echo "A"
elif [[ "$score" -ge 60 ]]; then
echo "pass"
else
echo "fail"
fiWhy: Bash uses DIFFERENT operators for numbers and text. The six numeric ones are abbreviations of English: -eq EQual, -ne Not Equal, -lt Less Than, -le Less than or Equal, -gt Greater Than, -ge Greater than or Equal. Strings use == != < > instead. Mixing them is a classic bug — "10" < "9" is true as strings but false as numbers.
#!/usr/bin/env bash
# Numeric comparison — the six operators
[[ 5 -eq 5 ]] && echo "-eq: equal"
[[ 5 -ne 9 ]] && echo "-ne: not equal"
[[ 5 -lt 9 ]] && echo "-lt: less than"
[[ 5 -le 5 ]] && echo "-le: less than or equal"
[[ 9 -gt 5 ]] && echo "-gt: greater than"
[[ 9 -ge 9 ]] && echo "-ge: greater than or equal"
# String comparison uses different operators
[[ "abc" == "abc" ]] && echo "strings equal"
[[ "$USER" != "root" ]] && echo "not running as root"Why: -z is true when a string is empty, -n when it is non-empty. This is how you check that a variable or argument was actually provided before using it.
#!/usr/bin/env bash
name="$1"
if [[ -z "$name" ]]; then
echo "no name given"
else
echo "hello, $name"
fiWhy: before reading or writing, check the file actually exists and is the right kind. -f true for a regular file, -d for a directory, -e for either, -r/-w/-x for readable/writable/executable. Note: the permission model behind these is covered in the Linux course lesson on permissions & ownership.
#!/usr/bin/env bash
config="/etc/app.conf"
if [[ -f "$config" ]]; then
echo "config exists"
fi
if [[ ! -d "/var/cache/app" ]]; then
mkdir -p /var/cache/app # create it if the dir is missing
fiWhy: && means "and" (both must hold), || means "or" (either holds), and ! negates. Inside [[ ]] they let you express compound checks without nesting if statements.
#!/usr/bin/env bash
age=25
if [[ "$age" -ge 18 && "$age" -lt 65 ]]; then
echo "working age"
fi
# As a guard: run the second part only if the first succeeds
[[ -f data.txt ]] && echo "found it" || echo "missing"Why: when you compare one variable against several patterns, case is cleaner than a long if/elif chain. Each branch ends with ;;, and *) is the catch-all default. Patterns support globs and | for alternatives.
#!/usr/bin/env bash
case "$1" in
start) echo "starting" ;;
stop) echo "stopping" ;;
restart|reload) echo "restarting" ;;
*) echo "Usage: $0 {start|stop|restart}" ;;
esac