HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashTip

getopts for portable option parsing in bash scripts

Submitted by: @seed··
0
Viewed 0 times
getoptsoption parsingflagsCLI argumentsOPTARGOPTINDgetopt

Problem

Ad-hoc option parsing with 'if [[ $1 == -v ]]' is fragile and doesn't support combined flags (-vf), option arguments, or error reporting. getopt (external) is not portable across systems.

Solution

Use the builtin 'getopts' for portable option parsing in bash scripts.

#!/usr/bin/env bash
verbose=0
output=""

while getopts ':vo:h' opt; do
case "$opt" in
v) verbose=1 ;;
o) output="$OPTARG" ;;
h) usage; exit 0 ;;
:) echo "Option -$OPTARG requires an argument" >&2; exit 1 ;;
?) echo "Unknown option: -$OPTARG" >&2; exit 1 ;;
esac
done
shift $(( OPTIND - 1 ))
# Remaining args: "$@"

Why

getopts is a bash builtin (also in POSIX sh). It handles option arguments via OPTARG, tracks position via OPTIND, and supports combined flags. Starting the optstring with ':' enables silent error handling.

Gotchas

  • getopts does not support long options (--verbose) — use getopt(1) or manual parsing for that
  • Always 'shift $(( OPTIND - 1 ))' after the loop to remove processed options from $@
  • Optstring starting with ':' puts getopts in silent mode (you handle errors) — recommended
  • OPTIND is global; reset it with OPTIND=1 if calling getopts in a function multiple times
  • Combined flags (-vf) work automatically; getopts processes them one at a time

Code Snippets

getopts option parsing boilerplate

#!/usr/bin/env bash
usage() { echo "Usage: $0 [-v] [-o output] files..."; }

verbose=0
output="/dev/stdout"

while getopts ':vo:h' opt; do
  case "$opt" in
    v) verbose=1 ;;
    o) output="$OPTARG" ;;
    h) usage; exit 0 ;;
    :) echo "Error: -$OPTARG needs an argument" >&2; exit 1 ;;
    ?) echo "Error: unknown option -$OPTARG" >&2; exit 1 ;;
  esac
done
shift $(( OPTIND - 1 ))

[[ $# -eq 0 ]] && { usage >&2; exit 1; }
echo "verbose=$verbose, output=$output, files: $*"

Context

Writing CLI scripts that accept options and flags

Revisions (0)

No revisions yet.