Reputation: 732
I have a small script that takes five positional parameters, the first two of which are optional (-v
and -p
) and the last three mandatory (one
, two
, three
). The second optional parameter takes an argument. So far I have this:
#!/bin/bash
verbose=
altpath=
while getopts ":vp:" opt; do
case $opt in
v) echo "-v triggered"
verbose=true
;;
p) echo "-p triggered, param: $OPTARG"
altpath=$OPTARG
;;
\?) echo "invalid option: -$OPTARG."
exit 1
;;
:) echo "option -$OPTARG requires an argument."
exit 1
;;
esac
done
shift "$((OPTIND-1))"
Now, if I run the script as it should be run, it behaves as expected:
$ myscript -v -p argname one two three
However, if I forget the argname
parameter
$ myscript -v -p one two three
it does not say 'option -p requires an argument', but rather takes one
as the argument for -p
. Not what I want, obviously.
I understand why this happens, but I can't figure out how to solve it.
Upvotes: 1
Views: 3445
Reputation: 43970
I would recommend to test whether there are three unprocessed arguments left once getopts has finished its work. If it is not the case, abort and print an error message.
For example, add this at the end of the script:
shift "$((OPTIND-1))"
if [ ! $# -eq 3 ] ; then
echo "Expected three mandatory arguments"
exit 1
fi
Forcing an error if the argument of -p
is omitted, is not directly supported. As a workaround, you can test whether the next argument is either missing or starts with a dash. For instance:
p) if [ -z "$OPTARG" -o "${OPTARG:0:1}" = "-" ] ; then
echo "Error: -p requires an argument"
exit 1
fi
echo "-p triggered, param: $OPTARG"
altpath=$OPTARG
;;
Here is the full script:
#!/bin/bash
verbose=
altpath=
while getopts ":vp:" opt; do
case $opt in
v) echo "-v triggered"
verbose=true
;;
p) if [ -z "$OPTARG" -o "${OPTARG:0:1}" = "-" ] ; then
echo "Error: -p requires an argument"
exit 1
fi
echo "-p triggered, param: $OPTARG"
altpath=$OPTARG
;;
\?) echo "invalid option: -$OPTARG."
exit 1
;;
:) echo "option -$OPTARG requires an argument."
exit 1
;;
esac
done
shift "$((OPTIND-1))"
if [ ! $# -eq 3 ] ; then
echo "Expected three mandatory arguments"
exit 1
fi
Upvotes: 3