Not a comprehensive Bash guide. Just the patterns I reach for repeatedly and had to look up too many times before they stuck.

Safe script header

Every script I write starts with:

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

-e exits on error. -u treats unset variables as errors. -o pipefail catches failures in pipelines (without it, false | true returns 0). The IFS change prevents word splitting on spaces — relevant if you’re iterating over filenames.

Checking if a command exists

if ! command -v jq &>/dev/null; then
    echo "jq is required but not installed" >&2
    exit 1
fi

Don’t use which — it’s not portable and some systems don’t have it.

Default values for variables

NAME="${1:-world}"
echo "hello, $NAME"

${VAR:-default} uses default if VAR is unset or empty. ${VAR:=default} also assigns the default to VAR. I use the former almost exclusively.

Reading a file line by line

while IFS= read -r line; do
    echo "line: $line"
done < input.txt

The IFS= prevents leading/trailing whitespace from being stripped. -r prevents backslash interpretation. This is the safe way — for line in $(cat file) breaks on spaces and is slower.

Temporary files and cleanup

tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT

# use $tmp safely — it's cleaned up on script exit, even on error

mktemp gives you a guaranteed unique filename in /tmp. The trap on EXIT runs the cleanup whether the script exits normally, on error, or on signal.

Checking if running as root

if [[ $EUID -ne 0 ]]; then
    echo "this script must be run as root" >&2
    exit 1
fi

Logging with timestamps

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }

log "starting deployment"

Simple, no dependencies, readable in cron output.

Running a command with a timeout

timeout 30 some-command || echo "timed out or failed"

timeout is in GNU coreutils — available on any modern Linux. Useful for network calls in scripts where you can’t guarantee the remote responds.

These patterns cover maybe 80% of what I write in Bash. For anything heavier than this, I switch to Python.