Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Example of how to parse options with bash/getopt
#!/bin/bash
#
# Example of how to parse short/long options with 'getopt'
#
OPTS=`getopt -o vhns: --long verbose,dry-run,help,stack-size: -n 'parse-options' -- "$@"`
if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
echo "$OPTS"
eval set -- "$OPTS"
VERBOSE=false
HELP=false
DRY_RUN=false
STACK_SIZE=0
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-h | --help ) HELP=true; shift ;;
-n | --dry-run ) DRY_RUN=true; shift ;;
-s | --stack-size ) STACK_SIZE="$2"; shift; shift ;;
-- ) shift; break ;;
* ) break ;;
esac
done
echo VERBOSE=$VERBOSE
echo HELP=$HELP
echo DRY_RUN=$DRY_RUN
echo STACK_SIZE=$STACK_SIZE

Nice. Though a little explanation on what is happening inside the case/esac would help the new-bees.

Super!

Not bad, not bad at all.

drveera commented May 18, 2016

Do you know how to prevent passing parameters to arguments that doesn't take one ?
For example
if i call
sh parse-options.sh -h hello

it should throw an error saying that -h doesn't take parameter values

Do anyone knows how to do it ?

@veera-dr It depends on whether your program takes non-option arguments. If parse-options.sh foo bar would be a valid invocation, you would need to follow every single option in your getopt string with :: and then test every output option to see if it has an argument attached or not.

If your program wouldn't normally take any arguments, you could just test for arguments in * and throw an error if you find any. For example:

while true; do
    case "$1" in
        -a ) OPT_A=true;;
        -b ) OPT_B=true;;
        -- ) ;;
        * ) if [ -z "$1" ]; then break; else echo "$1 is not a valid option"; exit 1; fi;;
    esac
    shift
done

A subtlety, I woud change shift; shift for shift 2.

As stack-size was the only option that takes a value, it would've been a better idea to not put it last:

  • Why's the colon there? does the --long list always end with a colon, or is it part of stack-size option definition?
  • It takes a numeric value and getopt's -n switch confused the hell out of me:
    • does it belong to the stack-size: option definition ("takes numeric value?") OR
    • is it something else?

Upon investigating, it seems to be just a switch to ´getopt´, so IMO this would have been clearer:

getopt -n 'parse-options' -o vhns: --long verbose,stack-size:,dry-run,help -- "$@"`

Decstasy commented Jun 29, 2017 edited

I have written a faster version by myself which does not need the external program getopt to parse long options. It is compatible to bash 3,4 and ksh (fastest). Surely there are more compatible shell's but this are the shells I have tested. It is a little bit more advanced than your version but easy to maintain. Click here to see it on gist.github.com

davidechicco commented Jul 17, 2017 edited

Thanks for the code. A question, for anyone who can help me: how to edit the code to let the script read another integer value as well?
For example, suppose you want to include the numeric integer -x parameter (long: --xxx-size).

The new input line should work for something like: ./parse-options.sh -s 20 -x 100

How can you do that? I tried by duplicating the STACK_SIZE line but it did not work. Thanks!

@davidechicco it took me a while to figure this out because get-opt is cryptic, but the colon at the end of stack-size: in the get-opt command means "requires argument". http://www.bahmanm.com/blogs/command-line-options-how-to-parse-in-bash-using-getopt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment