7.1. if/elif/else and case Statements#
Two powerful ways to make decisions in bash: sequential conditions and pattern matching.
7.1.1. Common Pitfalls#
7.1.1.1. ❌ Missing Quotes in Conditions#
# Wrong: unquoted $var can break
user=$1
if [ $user = "admin" ]; then # Fails if user empty!
echo "admin"
fi
# Correct: always quote variables
if [ "$user" = "admin" ]; then
echo "admin"
fi
7.1.1.2. ❌ Missing Semicolon Before fi/done#
# Wrong: no ; before fi
if [ -f "$file" ]
then
echo "found"
fi # Error!
# Correct: semicolon (or newline) required
if [ -f "$file" ]; then
echo "found"
fi
7.1.1.3. ❌ Not Using ;; in case#
# Wrong: missing ;; causes fall-through
case $var in
a) echo "a"
b) echo "b" # This always runs after a!
esac
# Correct: each case ends with ;;
case $var in
a) echo "a" ;;
b) echo "b" ;;
esac
7.1.2. Comparison: if/elif vs case#
7.1.2.1. When to use if/elif#
# Good for: Complex conditions, ranges, comparisons
if [ $count -gt 100 ]; then
echo "Too many"
elif [ $count -gt 50 ]; then
echo "Many"
else
echo "Few"
fi
Best for:
Range checks (>, <, >=, <=)
Combining multiple conditions (&&, ||, !)
File/string tests (-f, -z, etc.)
7.1.2.2. When to use case#
# Good for: Matching one variable against patterns
case $option in
-v|--verbose) verbose=1 ;;
-q|--quiet) quiet=1 ;;
-h|--help) show_help ;;
esac
Best for:
Single variable, multiple patterns
Command-line options/arguments
File extensions or types
Cleaner, more readable code
7.1.2.3. Combining Conditions with &&, ||, and ()#
Nest conditions for complex logic:
#!/bin/bash
file=$1
action=$2
if [ -f "$file" ] && [ -r "$file" ]; then
case $action in
read)
cat "$file"
;;
count)
wc -l "$file"
;;
*)
echo "Unknown action"
;;
esac
elif [ ! -e "$file" ]; then
echo "File doesn't exist"
elif [ ! -r "$file" ]; then
echo "File not readable"
fi
7.1.2.4. Pattern Matching with Wildcards#
case supports glob patterns:
#!/bin/bash
filename=$1
case $filename in
*.txt)
echo "Text file"
;;
*.log)
echo "Log file"
;;
*.sh)
echo "Shell script"
;;
*.jpg|*.png|*.gif)
echo "Image file"
;;
*)
echo "Unknown file type"
;;
esac
Glob pattern examples:
*.txt- ends with .txtfile*- starts with “file”test[0-9]- test followed by digit?(pattern)- optional pattern (bash extglob)+(pattern)- one or more patterns@(a|b|c)- exactly one of a, b, or c
7.1.2.5. Simple case Example#
#!/bin/bash
command=$1
case $command in
start)
echo "Starting service..."
;;
stop)
echo "Stopping service..."
;;
restart)
echo "Restarting service..."
;;
status)
echo "Service is running"
;;
*)
echo "Unknown command: $command"
echo "Use: start, stop, restart, or status"
exit 1
;;
esac
Usage:
$ bash service.sh start
Starting service...
$ bash service.sh unknown
Unknown command: unknown
Use: start, stop, restart, or status
7.1.3. case: Pattern Matching#
More elegant than if/elif for checking one variable against multiple patterns:
case $variable in
pattern1)
# code if variable matches pattern1
;;
pattern2)
# code if variable matches pattern2
;;
pattern3|pattern4)
# code if variable matches pattern3 OR pattern4
;;
*)
# default case (optional)
;;
esac
Key points:
Each pattern ends with
)Code block ends with
;;|means OR (alternative patterns)*is the default (catch-all)
7.1.3.1. if/elif/else#
Test multiple conditions in sequence:
if [ condition1 ]; then
# runs if condition1 is true
elif [ condition2 ]; then
# runs if condition1 false AND condition2 true
elif [ condition3 ]; then
# runs if conditions 1,2 false AND condition3 true
else
# runs if all conditions false
fi
Real example: Grade calculator
#!/bin/bash
score=$1
if [ $score -ge 90 ]; then
echo "Grade: A"
elif [ $score -ge 80 ]; then
echo "Grade: B"
elif [ $score -ge 70 ]; then
echo "Grade: C"
elif [ $score -ge 60 ]; then
echo "Grade: D"
else
echo "Grade: F"
fi
Best practices:
Test most likely conditions first for efficiency
Use clear, simple conditions
Avoid deeply nested if/elif chains (use case instead)
7.1.3.2. if/else#
if [ condition ]; then
# runs if true
else
# runs if false
fi
Real example:
#!/bin/bash
age=$1
if [ $age -ge 18 ]; then
echo "You are an adult"
else
echo "You are a minor"
fi
7.1.3.3. Basic if#
if [ condition ]; then
# code runs if condition is true
fi
Real example:
#!/bin/bash
file="$1"
if [ -f "$file" ]; then
echo "File exists"
wc -l "$file"
fi
7.1.4. if/elif/else: Sequential Decision Making#
Test conditions in order and execute the first one that matches: