Trapping getopt invalid options
Solution 1
This sort of style works for me:
params="$(getopt -o d:h -l diff:,help --name "$cmdname" -- "$@")"
if [ $? -ne 0 ]
then
usage
fi
eval set -- "$params"
unset params
while true
do
case $1 in
-d|--diff)
diff_exec=(${2-})
shift 2
;;
-h|--help)
usage
exit
;;
--)
shift
break
;;
*)
usage
;;
esac
done
Solution 2
I found this to work as the last item in the getopts case statement:
*) eval echo "Unrecognized arg \$$[OPTIND-1]"; usage; exit ;;
Solution 3
This is not the most robust solution, but it's reasonable; it relies on the following:
- The error message that
getopt
prints is prefixed with "getopt: " - The assumption is that it's acceptable to pass through a cleaned-up version of
getopt
's error message, augmented with custom information.
Code snippet:
# Invoke getopt; suppress its stderr initially.
args=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@" 2>/dev/null)
if [[ $? -ne 0 ]]; then # getopt reported failure
# Rerun the same getopt command so we can capture stderr output *only* this time.
# Inefficient (and a potential maintenance headache, if literals were involved), but this will only execute in case of invalid input.
# Alternatively, redirect the first getopt invocation's stderr output to a temp. file and read it here.
errmsg=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@" 2>&1 1>&-)
# Strip getopt's prefix and augment with custom information.
echo -e "${errmsg#getopt: }\nTry './cmd.sh --help for more information." 1>&2
exit 1
fi
Solution 4
Do you have to use getopt at all? If you just use
while [ $# -gt 0 ]; do
case "$1" in
-d|--diff)
diff_exec=(${2-})
shift
;;
-h|--help)
usage
exit
;;
--)
break
;;
*)
usage
;;
esac
shift
done
Then you own code is doing the checking.
Tom Auger
Developer, designer, business owner. jQuery, AS3, WordPress, Perl, PHP
Updated on June 04, 2022Comments
-
Tom Auger about 2 years
I'm using
getopt
(notgetops
) to provide the ability for my bash script to process options and switches (both long --option and short -o forms).I'd like to be able to trap invalid options and handle them, typically echoing out that the user should try
cmd --help
and then exiting the script.Thing is, the invalid options are being caught by getopt, which is itself outputting a message such as "getopt: invalid option -- 'x'"
Here's the pattern I'm using to set my getopt parameters:
set -- $(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@")
where both $LONG_OPTIONS and $SHORT_OPTIONS are a comma-delimited list of options.
Here's how I handle processing the options:
while [ $# -gt 0 ] do case "$1" in -h|--help) cat <<END_HELP_OUTPUT Help ---- Usage: ./cmd.sh END_HELP_OUTPUT shift; exit ;; --opt1) FLAG1=true shift ;; --opt2) FLAG2=true shift ;; --) shift break ;; *) echo "Option $1 is not a valid option." echo "Try './cmd.sh --help for more information." shift exit ;; esac done
getopt -q
will suppress the output, but my trapping scheme within thecase
statement still fails to do what I expect. Instead, the program just executes, despite the invalid arguments. -
mklement0 about 12 years@TomAuger: If you think that "pretty fragile" adequately paraphrases "not the most robust, but it's reasonable", you must be running an incompatible English-language shell. Invariably, trying to get information out of
getopt
reliably that it wasn't designed to report programmatically will be tricky. That said, the part about assuming that stderr output comes first is indeed shaky, so I've revised the code to address that. If you how to capture stdout and stderr into separate variables from a single command execution (not involving explicit creation of temporary files), let me know. -
Rhys Ulerich almost 12 yearsUsing ':' as the first character within optstring suppresses the message output. However, the return code from getopt(1) is still nonzero and the unrecognized option does not get output by getopt(1).
-
jarno over 7 yearsIn which case *) is reached?
-
l0b0 over 7 years@jarno If you ever have a mismatch between your
case
statement and thegetopt
call, it will be caught there. It's just defensive programming.