Parsing command line options makes a Bash script safer to run repeatedly because each input has a named flag instead of relying on positional order alone. A script that accepts ./report-options.sh -n backups -v is easier to read in history, cron entries, and saved runbooks than a script that expects several unnamed arguments.

The getopts builtin reads short options one at a time, stores option arguments in OPTARG, and advances OPTIND so the script can separate parsed flags from remaining file or path arguments. A leading colon in the option string lets the script print its own missing-argument and invalid-option messages.

The example below handles a required -n NAME option, an optional -v flag, and remaining file names. It stays with short options because getopts does not implement GNU-style long options such as --name without additional parsing.

Steps to parse command line options in Bash with getopts:

  1. Create a script file for the option parser.
    report-options.sh
    #!/usr/bin/env bash
    set -euo pipefail
     
    usage() {
        printf "Usage: %s -n NAME [-v] [FILE...]\n" "${0##*/}" >&2
    }
     
    verbose=0
    name=""
     
    while getopts ":n:vh" opt; do
        case "$opt" in
            n) name=$OPTARG ;;
            v) verbose=1 ;;
            h) usage; exit 0 ;;
            :) printf "Missing argument for -%s\n" "$OPTARG" >&2; usage; exit 2 ;;
            \?) printf "Invalid option: -%s\n" "$OPTARG" >&2; usage; exit 2 ;;
        esac
    done
     
    shift "$((OPTIND - 1))"
     
    if [ -z "$name" ]; then
        printf "Missing required option: -n\n" >&2
        usage
        exit 2
    fi
     
    printf "name=%s\n" "$name"
    printf "verbose=%s\n" "$verbose"
    printf "remaining=%s\n" "$*"

    The option string :n:vh means n requires an argument, v and h do not, and the script handles option errors itself.

  2. Check the script syntax before running option tests.
    $ bash -n report-options.sh

    No output means Bash did not find a syntax error while parsing the script.

  3. Run the script with both supported options and extra file arguments.
    $ bash report-options.sh -v -n backups archive.log access.log
    name=backups
    verbose=1
    remaining=archive.log access.log

    The shift "$((OPTIND - 1))" line removes parsed options so $* contains only the remaining non-option arguments.

  4. Confirm that a missing required option argument fails with a usage message.
    $ bash report-options.sh -n
    Missing argument for -n
    Usage: report-options.sh -n NAME [-v] [FILE...]
  5. Confirm that omitting the required -n option also exits with a nonzero status.
    $ bash report-options.sh -v
    Missing required option: -n
    Usage: report-options.sh -n NAME [-v] [FILE...]
    $ printf 'exit=%s\n' "$?"
    exit=2

    Run this check in a shell where set -e is not active, or capture the failure with an explicit conditional, because the script is expected to exit with status 2.

  6. Remove the sample script after the option parser tests are finished.
    $ rm -f report-options.sh