Last active
May 15, 2025 21:02
-
-
Save mattmc3/64bc4da0235b757fb6ec3f066c2b9f0e to your computer and use it in GitHub Desktop.
Bash getopts - normalize flags
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Normalize --long-flags to -s short ones for use with getopts. | |
normalize_flags() { | |
local shortopt longopt | |
local -a args=() | |
local -A spec=() | |
# Process option definitions until we hit the -- separator | |
while [[ "$#" -gt 0 && "$1" != -- ]]; do | |
# Split the "short/long" option spec and save the mapping | |
shortopt="${1%%/*}" | |
longopt="${1#*/}" | |
spec["--${longopt}"]="-${shortopt}" | |
shift | |
done | |
# Check for the required -- separator | |
if [[ "$1" != -- ]]; then | |
printf >&2 'normalize_args: %s\n' "Missing required -- separator" | |
return 1 | |
fi | |
shift # Skip the -- separator | |
# Handle longopt to shortopt conversion, | |
# respecting anything after an optional -- | |
while [[ "$#" -gt 0 ]]; do | |
if [[ -n "${spec["$1"]}" ]]; then | |
args+=("${spec["$1"]}") | |
elif [[ "$1" == -- ]]; then | |
args+=("$@") | |
break | |
else | |
args+=("$1") | |
fi | |
shift | |
done | |
# Return new args via the reply array | |
typeset -ga reply=("${args[@]}") | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Usage | |
# call normalize_flags defining -s short to --long option mappings where appropriate | |
normalize_flags 'a/any' 'd/do-something' 'h/help' 'v/version' 'x/extra' -- "$@" | |
set -- "${reply[@]}" | |
unset reply | |
# Use getopts confidently, now that all options are short | |
while getopts ":adhvx:" opt; do | |
case "$opt" in | |
a) echo "Option A" ;; | |
h) echo "Help" ;; | |
d) echo "Option D" ;; | |
v) echo "Version" ;; | |
z) echo "Extra: $OPTARG" ;; | |
\?) echo "Invalid option"; return 1 ;; | |
esac | |
done | |
# Ensure OPTIND is at least 1 before shifting | |
[[ $OPTIND -gt 1 ]] && shift $((OPTIND - 1)) | |
unset OPTARG OPTIND OPTOPT |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment