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
Portable Bash shebang
#!/usr/bin/env bash

# Use env to locate Bash on PATH.

Get script directory
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)

# Resolve the directory of the current script.

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

# Implement manual flag parsing in Bash.

Parse short options with getopts
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

# Parse short options using the getopts builtin.

Shift parsed options away
shift $((OPTIND - 1))

# Drop parsed options after getopts completes.

## Files and Temporary Paths
Create temp file
tmp=$(mktemp)

# Create a secure temporary file.

Create temp directory
tmpdir=$(mktemp -d)

# Create a secure temporary directory.

Copy file if contents differ
cmp -s new.conf current.conf || cp new.conf current.conf

# Avoid replacing files unnecessarily.

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

# Require a dependency before running script logic.

Walk up to repo root
dir=$PWD
while [[ $dir != / && ! -d $dir/.git ]]; do dir=$(dirname "$dir"); done
echo "$dir"

# Walk upward until a matching parent directory is found.

## Logging and Output
Simple log function
log() { printf '[%s] %s
' "$(date +%H:%M:%S)" "$*"; }

# Print timestamped log lines.

Warn and error helpers
warn() { printf 'WARN: %s
' "$*" >&2; }
die() { printf 'ERROR: %s
' "$*" >&2; exit 1; }

# Use reusable stderr helpers for diagnostics.

Mirror output to screen and file
./deploy.sh 2>&1 | tee deploy.log

# Write output to terminal and log file.

## Automation Recipes
Retry command with delay
for attempt in {1..5}; do
  curl -sf http://localhost:8080/health && break
  sleep 2
done

# Retry a command several times before giving up.

Bound command runtime
timeout 30s bash -lc 'long_running_job'

# Stop a command if it runs too long.

Run two jobs in parallel and wait
job1 &
pid1=$!
job2 &
pid2=$!
wait "$pid1" "$pid2"

# Start jobs in background and wait for both.

Use Bash with jq safely
user=$(jq -r '.user.name' payload.json)
echo "$user"

# Combine Bash with jq for reliable JSON parsing.

Generate config with variable expansion
cat > app.env <<EOF
APP_ENV=${APP_ENV:-dev}
PORT=${PORT:-3000}
EOF

# Create small config files from shell variables.