Lesson 3 of 9 · 20m
Shell Scripting: When Bash Is Enough
Shell scripts that don't embarrass you — strict mode, quoting, exit codes, and when to reach for Python instead.
Bash is a language for gluing other programs together — reach for it when the job is "run these commands in order" and reach for a real language when the job is "process this data."
Strict mode first
#!/usr/bin/env bash
set -euo pipefail
IFS=$'
'-e— exit on first failure (no silently continuing on a broken pipe).-u— unset variables are errors, not empty strings.-o pipefail— a pipeline fails if any stage fails, not just the last.IFS— word-splitting on newline/tab, not spaces (spaces in filenames work).
Quoting is a discipline
for f in *.txt; do echo "$f"; done # "$f" — quoted, preserves spaces
for f in *.txt; do echo $f; done # $f — unquoted, word-splits — usually a bug$var without quotes splits on whitespace and glob-expands — file="my doc.txt"; rm $file deletes my and doc.txt. Always "$var".
The script structure that works
#!/usr/bin/env bash
set -euo pipefail
usage() { echo "Usage: $0 <environment>"; exit 1; }
[ $# -lt 1 ] && usage
ENV=$1
main() {
case "$ENV" in
staging|prod) echo "deploying to $ENV"; deploy "$ENV" ;;
*) echo "unknown env"; usage ;;
esac
}
main "$@"Functions, a main, argument validation, a usage function — the script is readable and testable.
When to stop using bash
- String manipulation beyond simple substitution → Python/awk.
- JSON parsing → jq, not regex.
- Complex data structures → a real language.
- Anything where error handling matters → Python's
try/exceptbeats|| echo "failed".
::exercise(strict-mode)
Field notes
shellcheckis a linter for shell scripts — it catches quoting bugs,cdwithoutcd || exit, andforoverls. Run it before committing any script.trap 'echo "interrupted"; exit 130' INT— cleanup on Ctrl+C; the script that doesn't trap leaves partial state behind.command -v docker &>/dev/null || { echo "install docker"; exit 1; }— dependency check pattern.