I wish to have long and short forms of command line options invoked using my shell script.
I know that getopts
can be used, but like in Perl, I have not been able to do the same with shell.
Any ideas on how this can be done, so that I can use options like:
./shell.sh --copyfile abc.pl /tmp/
./shell.sh -c abc.pl /tmp/
In the above, both the commands mean the same thing to my shell, but using getopts
, I have not been able to implement these?
Another way...
The bash
getopts
builtin does not support long option names with the double-dash prefix. It only supports single-character options.There is a shell tool
getopt
which is another program, not a bash builtin. The GNU implementation ofgetopt(3)
(used by the command-linegetopt(1)
on Linux) supports parsing long options.But the BSD implementation of
getopt
(e.g. on Mac OS X) does not support long options.Some other answers show a solution for using the bash builtin
getopts
to mimic long options. That solution actually makes a short option whose character is "-". So you get "--" as the flag. Then anything following that becomes OPTARG, and you test the OPTARG with a nestedcase
.This is clever, but it comes with caveats:
getopts
can't enforce the opt spec. It can't return errors if the user supplies an invalid option. You have to do your own error-checking as you parse OPTARG.So while it is possible to write more code to work around the lack of support for long options, this is a lot more work and partially defeats the purpose of using a getopt parser to simplify your code.
The built-in
getopts
command is still, AFAIK, limited to single-character options only.There is (or used to be) an external program
getopt
that would reorganize a set of options such that it was easier to parse. You could adapt that design to handle long options too. Example usage:You could use a similar scheme with a
getoptlong
command.Note that the fundamental weakness with the external
getopt
program is the difficulty of handling arguments with spaces in them, and in preserving those spaces accurately. This is why the built-ingetopts
is superior, albeit limited by the fact it only handles single-letter options.I wanted something without external dependencies, with strict bash support (-u), and I needed it to work on even the older bash versions. This handles various types of params:
Just insert the following at the top of your script:
And use it like so:
Maybe it's simpler to use ksh, just for the getopts part, if need long command line options, as it can be easier done there.
In
ksh93
,getopts
does support long names...Or so the tutorials I have found have said. Try it and see.