Creating Reusable Bash Script Templates for Efficiency

Build reusable Bash script templates with strict mode, usage text, logging, cleanup, and safe getopts argument parsing.

Creating Reusable Bash Script Templates for Efficiency

Reusable Bash script templates help you stop rewriting the same safety checks every time you automate a task. A good template gives your script strict error handling, predictable logging, usage help, argument parsing, and cleanup hooks before you add project-specific logic.

The goal is not a huge framework. It is a small starting point that keeps routine scripts consistent and easier to debug.

Why Use Script Templates?

Templates are useful when your team writes many small scripts for backups, deployments, reports, log cleanup, or data movement. Without a template, each script tends to handle errors, options, and logging a little differently.

A reusable template gives you:

  • Consistent strict mode and quoting habits.
  • A standard usage function.
  • One place for logging helpers.
  • A cleanup hook for temporary files and locks.
  • Predictable command-line parsing with getopts.

The Core Template Pieces

Start with Bash itself, then turn on strict behavior:

#!/usr/bin/env bash
set -euo pipefail

set -e exits on many unhandled command failures, set -u treats unset variables as errors, and set -o pipefail catches failures inside pipelines. You still need explicit checks for failures you expect, but strict mode catches many accidental mistakes.

Add a script name and a short usage block:

readonly SCRIPT_NAME="$(basename "$0")"

usage() {
    cat <<USAGE
Usage: $SCRIPT_NAME [-v] [-o output_dir] input_file

Options:
  -v              Enable verbose logging
  -o output_dir   Write output to this directory
  -h              Show this help message
USAGE
}

Use small logging helpers instead of scattered echo calls:

log_info() {
    [[ "$VERBOSE" -eq 1 ]] && printf '[INFO] %s\n' "$1"
}

die() {
    printf '[ERROR] %s\n' "$1" >&2
    exit 1
}

If the script creates temporary files or lock files, add a cleanup function early:

cleanup() {
    # Remove temp files or release locks here.
    :
}

trap cleanup EXIT

Safe Argument Parsing with getopts

Most reusable templates need flags. Bash's built-in getopts is enough for short options such as -v and -o output_dir.

VERBOSE=0
OUTPUT_DIR="."

while getopts ":vo:h" opt; do
    case "$opt" in
        v) VERBOSE=1 ;;
        o) OUTPUT_DIR=$OPTARG ;;
        h) usage; exit 0 ;;
        :) die "Option -$OPTARG requires an argument" ;;
        \?) die "Unknown option: -$OPTARG" ;;
    esac
done
shift "$((OPTIND - 1))"

INPUT_FILE=${1:-}
[[ -n "$INPUT_FILE" ]] || { usage >&2; exit 1; }
[[ -f "$INPUT_FILE" ]] || die "Input file not found: $INPUT_FILE"

The leading : in ":vo:h" lets your script handle missing option arguments itself. After parsing, shift "$((OPTIND - 1))" removes the parsed options so positional arguments are easier to read.

A Compact Template You Can Reuse

Here is a practical starting point for small operations scripts:

#!/usr/bin/env bash
set -euo pipefail

readonly SCRIPT_NAME="$(basename "$0")"
VERBOSE=0
OUTPUT_DIR="."

usage() {
    cat <<USAGE
Usage: $SCRIPT_NAME [-v] [-o output_dir] input_file
USAGE
}

log_info() {
    [[ "$VERBOSE" -eq 1 ]] && printf '[INFO] %s\n' "$1"
}

die() {
    printf '[ERROR] %s\n' "$1" >&2
    exit 1
}

cleanup() {
    :
}
trap cleanup EXIT

while getopts ":vo:h" opt; do
    case "$opt" in
        v) VERBOSE=1 ;;
        o) OUTPUT_DIR=$OPTARG ;;
        h) usage; exit 0 ;;
        :) die "Option -$OPTARG requires an argument" ;;
        \?) die "Unknown option: -$OPTARG" ;;
    esac
done
shift "$((OPTIND - 1))"

INPUT_FILE=${1:-}
[[ -n "$INPUT_FILE" ]] || { usage >&2; exit 1; }
[[ -f "$INPUT_FILE" ]] || die "Input file not found: $INPUT_FILE"
mkdir -p "$OUTPUT_DIR"

log_info "Processing $INPUT_FILE"
# Add your script logic here.

Keep the template short. Add shared functions only when several scripts truly need them. A template should remove repeated setup work, not make every script feel like a framework.