Bash Scripting Patterns and Practical Recipes

Production-minded Bash script patterns for files, arguments, parsing, temp files, logging, retries, and common automation tasks.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all

Script Structure

Shebangs, argument handling, and reusable script patterns.

Portable Bash shebang

Use env to locate Bash on PATH.

bashANYshebangscripts
bash
#!/usr/bin/env bash

Common when Bash may not live at /bin/bash.

Get script directory

Resolve the directory of the current script.

bashANYpathsscripts
bash
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)

Useful for loading sibling files and assets reliably.

Parse flags with while/case

Implement manual flag parsing in Bash.

bashANYargscase
bash
while (($#)); do
  case "$1" in
    -v|--verbose) verbose=1 ;;
    -o|--output) output=$2; shift ;;
    *) echo "unknown arg: $1" >&2; exit 1 ;;
  esac
  shift
done

A common pattern for lightweight scripts.

Parse short options with getopts

Parse short options using the getopts builtin.

bashANYgetoptsargs
bash
while getopts ':f:o:v' opt; do
  case $opt in
    f) file=$OPTARG ;;
    o) output=$OPTARG ;;
    v) verbose=1 ;;
    \?) echo "invalid option: -$OPTARG" ;;
  esac
done

Good for POSIX-style short flags in shell scripts.

Shift parsed options away

Drop parsed options after getopts completes.

bashANYgetoptsargs
bash
shift $((OPTIND - 1))

Leaves only positional arguments in $@.

Files and Temporary Paths

mktemp, safe file operations, and path helpers.

Create temp file

Create a secure temporary file.

bashANYmktemptempfiles
bash
tmp=$(mktemp)

Prefer mktemp over hand-rolled temp names.

Create temp directory

Create a secure temporary directory.

bashANYmktemptempfiles
bash
tmpdir=$(mktemp -d)

Pair with trap cleanup for robust scripts.

Copy file if contents differ

Avoid replacing files unnecessarily.

bashANYfilescmpcopy
bash
cmp -s new.conf current.conf || cp new.conf current.conf

Useful in deployment and config-management scripts.

Check if command exists

Require a dependency before running script logic.

bashANYdependenciescommand
bash
if ! command -v jq >/dev/null 2>&1; then echo 'jq required'; exit 1; fi

Portable and very common in setup scripts.

Walk up to repo root

Walk upward until a matching parent directory is found.

bashANYpathsgit
bash
dir=$PWD
while [[ $dir != / && ! -d $dir/.git ]]; do dir=$(dirname "$dir"); done
echo "$dir"

Useful for repo-aware scripts.

Logging and Output

Common script logging patterns.

Simple log function

Print timestamped log lines.

bashANYloggingfunctions
bash
log() { printf '[%s] %s
' "$(date +%H:%M:%S)" "$*"; }

Small helper that makes scripts easier to debug.

Warn and error helpers

Use reusable stderr helpers for diagnostics.

bashANYloggingstderr
bash
warn() { printf 'WARN: %s
' "$*" >&2; }
die() { printf 'ERROR: %s
' "$*" >&2; exit 1; }

Keeps scripts readable and consistent.

Mirror output to screen and file

Write output to terminal and log file.

bashANYloggingtee
bash
./deploy.sh 2>&1 | tee deploy.log

Great for CI logs and manual runs.

Automation Recipes

Common retry, timeout, and parallel patterns.

Retry command with delay

Retry a command several times before giving up.

bashANYretryautomation
bash
for attempt in {1..5}; do
  curl -sf http://localhost:8080/health && break
  sleep 2
done

Useful for service startup and network flakiness.

Bound command runtime

Stop a command if it runs too long.

bashANYtimeoutautomation
bash
timeout 30s bash -lc 'long_running_job'

Very useful in automation, though timeout is an external command.

Run two jobs in parallel and wait

Start jobs in background and wait for both.

bashANYparallelbackground
bash
job1 &
pid1=$!
job2 &
pid2=$!
wait "$pid1" "$pid2"

Useful in CI or local automation when tasks are independent.

Use Bash with jq safely

Combine Bash with jq for reliable JSON parsing.

bashANYjqjsonautomation
bash
user=$(jq -r '.user.name' payload.json)
echo "$user"

Prefer jq for structured JSON instead of fragile grep/sed hacks.

Generate config with variable expansion

Create small config files from shell variables.

bashANYtemplatesheredoc
bash
cat > app.env <<EOF
APP_ENV=${APP_ENV:-dev}
PORT=${PORT:-3000}
EOF

Common in local setup scripts and container entrypoints.