A dense engineer's reference covering script anatomy, variables, control flow, functions, arrays, process substitution, traps, error handling patterns, and the full builtin vocabulary.
Bash (Bourne Again SHell) is the default shell on most Linux distros and macOS (≤10.14). It is simultaneously an interactive command interpreter and a full scripting language for automation, DevOps, and system administration.
[[ ]])(( )) or exprbash script.sh or ./script.sh/etc/profile, ~/.bash_profile on start(cmd) forks; variable changes don't affect parentnameref. macOS ships Bash 3.2 (GPL2); install 5.x via Homebrew.
How Bash parses, expands, and executes every line — and the layered structure of a production-grade script.
/usr/bin/env bash over /bin/bash for portability across distros. Must be first line, no spaces.
set -euo pipefail — always use in production scripts
"$VAR" to prevent word splitting and globbing
$? holds last exit code · exit N to return from script
Conditionals, loops, case, and function definitions — the structural vocabulary of every Bash script.
Bash's data model — scalar variables, indexed arrays, associative arrays, and the powerful parameter expansion mini-language.
for key in "${!map[@]}"
Production patterns — trap-based cleanup, parallel jobs, here-docs, getopts parsing, and the ten most impactful idioms.
Structured step-by-step guides for the two most common real-world Bash scripting tasks.
[[ -f "$F" && -r "$F" ]] and wc -l sanity check. Exit early with clear message on failure.grep | awk | sort | uniq -c | sort -rn | head. Never load entire file into memory. Use while IFS= read -r line for line-by-line logic.$(mktemp), then mv to final destination. mv is atomic on same filesystem — readers never see partial output.printf '%s,%s\n' "$k" "$v". Log progress to stderr (>&2); keep stdout clean for piping downstream.command -v), environment vars set, disk space (df -k), and connectivity (nc -zw2 host port) before any changes.cp -a /opt/app /opt/app.bak.$(date +%s). Store current git SHA: PREV=$(git rev-parse HEAD). Register trap rollback ERR immediately after.curl -sf http://localhost/health in a retry loop (max N attempts with sleep backoff). Fail if health never passes.trap - EXIT to disarm. On failure (ERR trap fires): git checkout "$PREV", restore backup, restart, alert. Always exit non-zero on rollback.Commands that run inside the shell process — no fork overhead. Know these to avoid unnecessary subprocess spawns.
-r raw, -t timeout, -s silent (passwords)
$@; colon after letter = requires argument
$1 becomes former $N+1
$ on vars; C operators ++ -- ** % & | ^ ~ <<
BASH_REMATCH array
$(( RANDOM % N )) for range
"$VAR"
ls — use glob for f in /path/* or find instead
cd /nonexistent && rm -rf * = disaster. Use cd dir || die
=~: [[ $x =~ ^[0-9]+$ ]] not "^[0-9]+$"
cmd | while read runs in subshell — vars set inside won't persist. Use <(cmd) or lastpipe option
Six copy-ready reference cards — test operators, arithmetic, string ops, getopts template, parallel pattern, and debugging toolkit.