Search code examples
bashcommand-line-argumentsgetoptgetopts

Using getopts to process long and short command line options


I would like to have the long and short forms of command line options invoked using my shell script.

I know that getopts can be used, like in Perl, but I have not been able to implement the same using 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?


Solution

  • There are three implementations that may be considered:

    • Bash builtin getopts. This does not support long option names with the double-dash prefix. It only supports single-character options.

    • BSD UNIX implementation of standalone getopt command (which is what MacOS uses). This does not support long options either.

    • GNU implementation of standalone getopt. GNU getopt(3) (used by the command-line getopt(1) on Linux) supports parsing 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 nested case.

    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.
    • OPTARG is used for the long option name, which complicates usage when your long option itself has an argument. You end up having to code that yourself as an additional case.

    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.