Back to All Sheets
BashBash 5.xBEGINNER

Bash Shell Scripting

Bash reference covering quoting, parameters, arrays, tests, pipelines, functions, traps, files, processes, portability, security, debugging, and production-grade scripting.

60 min read
Category: Languages

Syntax, Expansion & Quoting

Options, Quoting & Expansion Order

Quote parameter expansions by default. Use arrays for argument lists and understand that shell parsing happens before commands receive arguments.

Quoting Reference
FormExpansionWord Splitting / GlobUse
'$value'NoneNoLiteral text
"$value"Parameter/command/arithmeticNoDefault variable use
$valueParameterYesRare intentional splitting
"${array[@]}"Each array elementNoSafe argument vector
bash
#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'
readonly script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
⚠️
Strict Mode Is Not Error Handling

set -e has contextual exceptions. Handle expected failures explicitly and test pipelines, conditions, subshells, and cleanup paths.

Parameters, Defaults & Arrays

Use parameter expansion for required/default values and indexed/associative arrays to preserve argument boundaries.

bash
environment=${ENVIRONMENT:-dev}
: "${DATABASE_URL:?DATABASE_URL is required}"
files=("report one.csv" "report two.csv")
declare -A ports=([http]=80 [https]=443)
command -- "${files[@]}"

Tests, Control Flow & Functions

[[ ]], Arithmetic, case & Loops

Prefer [[ ]] in Bash for strings/patterns, (( )) for arithmetic, case for dispatch, and read loops that preserve whitespace.

bash
if [[ -f $config && $environment == prod ]]; then load_config "$config"; fi
case $command in start|stop) run "$command" ;; *) usage >&2; exit 2 ;; esac
while IFS= read -r line; do process "$line"; done < "$input"

Functions, Exit Status & Traps

Functions return integer status, not rich values. Send data to stdout deliberately, diagnostics to stderr, and install cleanup traps early.

bash
tmp_dir=$(mktemp -d)
cleanup() { local status=$?; rm -rf -- "$tmp_dir"; exit "$status"; }
trap cleanup EXIT INT TERM
log() { printf '%s\n' "$*" >&2; }
🛑
Validate Destructive Targets

Before rm/mv/chmod, reject empty, root, home, unresolved, and unexpected paths. Prefer explicit paths over globs.

Processes, Pipelines & Files

Pipelines, Subshells & Background Jobs

Pipeline stages usually run in separate processes; pipefail surfaces earlier failures; capture PIDs and wait to own background work.

bash
producer | transformer | consumer
printf '%s\n' "${PIPESTATUS[@]}"
worker_one & pid_one=$!
worker_two & pid_two=$!
wait "$pid_one"; wait "$pid_two"

Files, find, NUL Delimiters & Portability

Use NUL delimiters for arbitrary filenames, -- before path operands, and select Bash versus POSIX sh deliberately.

bash
while IFS= read -r -d '' file; do
sha256sum -- "$file"
done < <(find "$root" -type f -print0)
⚠️
Never Parse ls

Filenames may contain spaces, tabs, newlines, and leading dashes. Use globs, find -print0, or arrays.

Debugging, Security & Review

Tracing, ShellCheck & Tests

Use bash -n for syntax, ShellCheck for static issues, controlled xtrace for debugging, and automated tests for edge-case inputs and failure paths.

bash
bash -n script.sh
shellcheck script.sh
PS4='+${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]}: ' bash -x script.sh

Production Checklist

Pin commands and formats, validate environment/input, avoid eval, preserve exit statuses, bound retries, and make reruns idempotent.

Production Checklist

Quote expansions, use arrays, validate paths, create secure temp files, trap cleanup, avoid secret xtrace, check dependencies, use timeouts, lint, test, and document Bash-only features.

Related References

Recommended Next Sheets