Reputation: 159
How do I flag an error in a bash script which requires an argument for getopt, but the user didn't pass it? e.g. the script below requires an argument for option "t":
#!/bin/bash
while getopts "ht:" OPTION
do
case $OPTION in
h)
echo "Hi"
;;
t)
echo You entered $OPTARG
;;
esac
done
I want to catch the below error and print something else and exit. Currently, it goes on to evaluate more arguments without exiting.
$ ./x.sh -h -t aa # (this is fine)
Hi
You entered aa
$ ./x.sh -h -t # (this is not handled)
Hi
No arg for -t option # (this error is being printed by bash)
Upvotes: 1
Views: 2046
Reputation: 54475
When it gets a failure, getopts
sets OPTION to a question mark (?
). You should add that to your case statement. As noted, that is a shell globbing character, requiring escaping.
getopts
is a built-in feature of bash
. Besides checking for the explicit ?
character, you can also use the bash
variable OPTERR
as mentioned in Using getopts in bash shell script to get long and short command line options.
The best place to find this information is in bash
's documentation. Oddly enough (given the number of extensions in bash
), it is in a section titled 4.1 Bourne Shell Builtins, and indeed there is a POSIX getopts for reference. The OPTERR
variable, however, is a bash
extension.
Upvotes: 2
Reputation: 44344
Several points here:
# Note the leading ':'
while getopts :ht: OPTION
do
case $OPTION in
h)
echo "Hi"
;;
t)
echo "You entered $OPTARG"
if [[ ${OPTARG:0:1} == '-' ]]; then
echo "Invalid value $OPTARG given to -$OPTION" >&2
exit 1
fi
;;
:) echo "$0: -$OPTARG needs a value" >&2;
exit 2
;;
\?) echo "$0: unknown option -$OPTARG" >&2;
exit 3
;;
esac
done
The leading ':' on the option list allows us to do our own error handling. If an unknown option is supplied then OPTION
is set to a ?
. Note that in the case
statement this has to be escaped (prefixed with a \
), otherwise it would match any single character.
If a value is not supplied to an option, then OPTION
is set to a :
. Unfortunately this does not help if someone does:
./x -t -h
since the -h
will be taken as the OPTARG
to option -t
. Hence the extra test.
Notice that all the error messages go to standard-error (>&2
). To halt the execution of the script we use exit
followed by a number in the range 0-255. The only number with a specific meaning is zero, which means success. The numbers 1-255 can have any meaning that we choose, but all imply failure.
Using your examples:
./x.sh -t -h
You entered -h
Invalid value -h given to -t
./x.sh -h -t aa
Hi
You entered aa
./x.sh -h -t
Hi
./x.sh: -t needs a value
./x.sh -t tea -c
You entered tea
./x.sh: unknown option -c
Upvotes: 4