Bash getopts should allow for options and arguments not to depend on position, as stated in tutorials and docs.
The following snippet of code could receive two options:
- a debug -d option which requires an argument
- a force -f option, without arguments.
I am seeing the strange behavior that only the first option listed gets processed correctly.
#!/bin/bash
## Defaults
DEBUG=INFO
forceOption=FALSE
## Usage
printUsage() {
echo " "
echo "USAGE: $0 [-d <DEBUG_LEVEL>] [ -f ]"
echo " "
exit 1
}
#
## Manage options before start
#
while getopts "hfd:" OPT
do
case $OPT in
h) printUsage ;;
f) forceOption="TRUE" ;;
d) debugLevel="$OPTARG" ;;
*) printUsage ;;
esac
shift `expr $OPTIND - 1`
done
if [ -n "$debugLevel" ] ; then
DEBUG="$debugLevel"
fi
echo "DEBUG : $DEBUG"
echo "Force : $forceOption"
You can see the faulty behavior below:
[rgulia$ ~] ./getopts.sh -d WARNING -f
DEBUG : WARNING
Force : FALSE
[rgulia$ ~] ./getopts.sh -f -d WARNING
DEBUG : INFO
Force : TRUE
The code parses correctly when the options are used separately or if -f precedes -d in the list of options and they are attached to each other
[rgulia$ ~] ./getopts.sh -f
DEBUG : INFO
Force : TRUE
[rgulia$ ~] ./getopts.sh -d WARNING
DEBUG : WARNING
Force : FALSE
[rgulia$ ~] ./getopts.sh -fd WARNING
DEBUG : WARNING
Force : TRUE
My impression is that the loop exits too early because it fails to compute OPTIND correctly when an option is passed an argument.
I did some tracing with printf statements for the values of OPT, OPTARG and OPTIND confirms such theory, but I still do not understand why it is happening and how to fix it.
Any suggestions?