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.
Related: How to create and run a Bash script
Related: How to use a case statement in Bash
Related: How to enable color output in Bash scripts
Steps to parse command line options in Bash with getopts:
- 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.
- 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.
- 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.
- 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...]
- 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.
- Remove the sample script after the option parser tests are finished.
$ rm -f report-options.sh
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.