patternbashTip
getopts for portable option parsing in bash scripts
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: "$@"
#!/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.