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
Updated: Jul 2026

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