Control Flow
Scope: if, loops, and case. All examples were run with
Bash 5.2.
if: [[ ]] not [ ]
age=20
if [[ $age -ge 18 ]]; then
echo "adult"
elif [[ $age -ge 13 ]]; then
echo "teenager"
else
echo "child"
fi
Use [[ ]] (double brackets), not the old [ ]:
[[ ]]is Bash-native: no word-splitting surprises, supports&&/||inside, and=~regex matching.- Numeric comparisons:
-eq-ne-lt-le-gt-ge. - String comparisons:
==!=, and-z(empty) /-n(non-empty).
name="Ada"
if [[ -z $name ]]; then echo "no name"; fi
if [[ $name == A* ]]; then echo "starts with A"; fi # glob pattern!
File tests you'll use constantly: -f (regular file exists),
-d (directory exists), -r/-w/-x (readable/writable/
executable).
while: read files line by line
while IFS= read -r line; do
echo "got: $line"
done < notes.txt
This is the idiom for processing a file line by line.
IFS= read -r preserves leading whitespace and backslashes —
copy it verbatim until you know why each piece is there.
Never do for line in $(cat file) — it word-splits and globs.
for: two flavors
# Over items (glob, list, command output via array)
for f in *.txt; do
echo "file: $f"
done
# C-style counting
for ((i = 0; i < 5; i++)); do
echo "$i"
done
for f in *.txt with no matches: by default the pattern stays
literal (*.txt). Add shopt -s nullglob to make it expand to
nothing instead.
case: Bash's switch
day="Sat"
case $day in
Sat|Sun) echo "weekend" ;;
Mon) echo "back to work" ;;
*) echo "weekday" ;;
esac
Patterns are globs (*.log, y|yes), ;; ends each branch,
*) is the default. Cleaner than if chains for matching
text.
&& and ||: the short-circuit idioms
[[ -f data.txt ]] && echo "exists"
mkdir -p build || exit 1
&& runs the right side only if the left succeeded; || only
if it failed. Great for one-liners — but don't chain them into
pseudo-if-statements; use a real if when logic gets complex.
select: quick menus (bonus)
select opt in "start" "stop" "quit"; do
echo "you chose: $opt"
break
done
Bash builds a numbered menu for free. Handy for interactive helper scripts.
Check
- [ ] You use
[[ ]]and can name two reasons it's better - [ ] You can write the
while readloop from memory - [ ] You know why
for line in $(cat file)is wrong
Next: Functions and Arguments.