Dualo
Bash / Shell Scripting

Control flow — if, for, while, case

Branch on exit codes, loop over lists or streams, match patterns. Bash control flow is quirky — exit code 0 means true.

1 min read

if checks exit codes, not booleans. if cmd; then ...; fi runs then if cmd exits 0. Counter-intuitive: exit 0 = success = 'true'; any non-zero = false. if grep -q foo file; then echo found; fi.

Tests: [[ expr ]] (Bash's modern test) and [ expr ] (POSIX). Examples: [[ -f file ]] (file exists), [[ -d dir ]] (directory exists), [[ -z $s ]] (empty string), [[ $a == $b ]] (string equal), [[ $n -lt 10 ]] (integer less than).

Loops: for x in a b c; do echo $x; done. Over files: for f in *.log; do ...; done. Numeric: for i in {1..5}; do ...; done. C-style: for ((i=0; i<5; i++)); do ...; done. While: while cmd; do ...; done.

case for multi-way branches: cleaner than chained if/elif. Uses glob patterns, not regex. Example: case "$env" in prod) ... ;; staging|dev) ... ;; *) default ;; esac. The ;; terminates each branch.

&& and || shorthand: cmd1 && cmd2 runs cmd2 only if cmd1 succeeds. cmd1 || cmd2 runs cmd2 only if cmd1 fails. mkdir -p dir && cd dir — idiomatic for 'create and enter'. cmd || echo failed for quick error messages.

Grounded on https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs

Next up

Functions & arguments

Group commands into reusable units, accept positional parameters, and return exit codes. Not quite like functions in 'real' languages.