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)
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