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?
Take a look at shFlags which is a portable shell library (meaning: sh, bash, dash, ksh, zsh on Linux, Solaris, etc.).
It makes adding new flags as simple as adding one line to your script, and it provides an auto generated usage function.
Here is a simple
Hello, world!
using shFlag:For OSes that have the enhanced getopt that supports long options (e.g. Linux), you can do:
For the rest, you must use the short option:
Adding a new flag is as simple as adding a new
DEFINE_ call
.In order to stay cross-platform compatible, and avoid the reliance on external executables, I ported some code from another language.
I find it very easy to use, here is an example:
The required BASH is a little longer than it could be, but I wanted to avoid reliance on BASH 4's associative arrays. You can also download this directly from http://nt4.com/bash/argparser.inc.sh
Th built-in OS X (BSD) getopt does not support long options, but the GNU version does:
brew install gnu-getopt
. Then, something similar to:cp /usr/local/Cellar/gnu-getopt/1.1.6/bin/getopt /usr/local/bin/gnu-getopt
.hm.
not really satisfied with the pure bash options. why not use perl to get what you want. Directly parse the $* array, and auto-name your options.
simple helper script:
then you can use in your script as a one liner, for example:
/tmp/script.sh hello --reuse me --long_opt whatever_you_want_except_spaces --hello 1 2 3
HELLO: 1 LONG_OPT: whatever_you_want_except spaces REUSE: me
1 2 3
Only caveat here is spaces don't work. But it avoids bash's rather complicated looping syntax, works with long args, auto-names them as variables and automatically resizes $*, so will work 99% of the time.
The built-in
getopts
can't do this. There is an external getopt(1) program that can do this, but you only get it on Linux from the util-linux package. It comes with an example script getopt-parse.bash.There is also a
getopts_long
written as a shell function.If all your long options have unique, and matching, first characters as the short options, so for example
Is the same as
You can use this before getopts to rewrite $args:
Thanks for mtvee for the inspiration ;-)