I wrote a bash script that takes flexible number of parameters and now I would like to add an optional argument (-l
) to each of them.
I am currently having difficulty getting the desired behavior.
I want all of the following to execute correctly:
./Script.sh arg1 arg2 arg3 -l opt
./Script.sh arg1 arg2 arg3
./Script.sh arg1 arg2 arg3 arg4 -l opt
./Script.sh arg1 arg2 arg3 arg4 arg5
The problem is that $OPTIND
cannot be set.
The following loop works if the -l opt
is placed before first argument.
while getopts ":l:" option
do
case "$option" in
t)
F_NAME=$OPTARG
;;
esac
done
shift $((OPTIND - 1))
However, place the optional -l
as last parameter is a requirement.
What's the easiest way to achieve this?
Here is a trick I have found to use arguments with optional parameters with getopts.
The way to manage the case where the optional parameter is inside the command is given by Jan Schampera in is reply on bash-hackers.org :
(see : http://wiki.bash-hackers.org/howto/getopts_tutorial deep in the page) But it does not manage the case where the option is given at the end of the command.
In that case, that is considered wrong because no parameter is given,
getopts
set theopt
variable to ':' (colon) andOPTARG
to the fault option value. So we have to manage the ':' case, with acase $OPTARG
.Let us say we write a script having three options :
a
: without parameterb
: with a required parameterv
: to set the verbosity with a value from0
to2
. The default value is0
and a preset value us used when the script is call with-v
without parameter or with a bad value.Here is the code :
getopts
conforms to the posix-standard command-line syntax where flag options come first. So it's not easy to use for non-standard cases.However, you may have the Gnu implementation of
getopt(1)
(seeman 1 getopt
), which can handle permuted option flags as well as long options. However, it's not as easy an interface.Or you can just interpret the argument yourself.
(Note: the above does not throw an error if the
-l
appears right at the end of the argument list; it just sets the option value to an empty string. If that's not appropriate, which it probably isn't, then insert some error checking.)