I'm having trouble wrapping my head around how to make getopts accept multiple flags with a single argument. For example.
Flags: Children: a - Adam b - Beth c - Cathy d - Duncan
Required parameter: ice cream flavor
(not what my script really does, but easiest to spell out this way)
What I can do right now:
./flavor -a chocolate
./flavor -c chocolate
What I'd like to do:
./flavor -acd chocolate
Rather than the only thing I can get it to do so far:
./flavor -a chocolate -c chocolate -d chocolate
Every variation I've tried with getopts either doesn't see the parameter at all or requires it after every single flag declaration. I feel like I'm missing something obvious that will give me the "aha" moment, but I'm not seeing it on my own. Can anyone point me in the right direction?
============================================
while getopts ":a:b:c:d:" opt; do
case $opt in
a)
do stuff with $OPTARG
;;
b)
do stuff with $OPTARG
;;
c)
do stuff with $OPTARG
;;
d)
do stuff with $OPTARG
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
============================================
My apologies if this is a really dumb question and thank you for your time.
Stacking options that require arguments is not supported by getopts. You can only stack options that do not take arguments.
To do what you propose, a lot more complication in the argument processing is required. Essentially you would have to pre-process the options to find out where the non-option arguments begin. This is not particularly beautiful or recommended, but this does literally what you asked for without requiring an additional option:
_GETOPTS=":abcd"
while getopts "${_GETOPTS}" opt
do
case $opt in
abcd)
:
;;
\?)
echo "Unsupported option (-${OPTARG})" >&2
exit 1
;;
esac
done
eval "FIRSTARG=\${${OPTIND}}"
if [ -z "${FIRSTARG}" ]
then
echo "Flavor argument required."
exit 1
fi
OPTIND=1
while getopts "${_GETOPTS}" opt
do
case $opt in
a)
echo do a stuff with ${FIRSTARG}
;;
b)
echo do b stuff with ${FIRSTARG}
;;
c)
echo do c stuff with ${FIRSTARG}
;;
d)
echo do d stuff with ${FIRSTARG}
;;
esac
done
Results:
$ ./flavor -acd chocolate
do a stuff with chocolate
do c stuff with chocolate
do d stuff with chocolate
One can access other arguments after the first non-option argument, but that would take a bit more work.
Note that handling the same set of options in multiple getopts statements is prone to create long term maintenance issues in that it might be too easy for the options handled by the two case statements to get out of sync.