Instantly share code, notes, and snippets.

Embed
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
@munsingh

This comment has been minimized.

Show comment
Hide comment
@munsingh

munsingh Sep 24, 2015

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

munsingh commented Sep 24, 2015

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

@EntityFX

This comment has been minimized.

Show comment
Hide comment
@EntityFX

EntityFX commented Nov 20, 2015

Super!

@akunaatrium

This comment has been minimized.

Show comment
Hide comment
@akunaatrium

akunaatrium Dec 14, 2015

Not bad, not bad at all.

akunaatrium commented Dec 14, 2015

Not bad, not bad at all.

@drveera

This comment has been minimized.

Show comment
Hide comment
@drveera

drveera 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 ?

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 ?

@demonbane

This comment has been minimized.

Show comment
Hide comment
@demonbane

demonbane Jul 26, 2016

@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

demonbane commented Jul 26, 2016

@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
@aguformoso

This comment has been minimized.

Show comment
Hide comment
@aguformoso

aguformoso Aug 31, 2016

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

aguformoso commented Aug 31, 2016

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

@joonas-fi

This comment has been minimized.

Show comment
Hide comment
@joonas-fi

joonas-fi Sep 9, 2016

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 -- "$@"`

joonas-fi commented Sep 9, 2016

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

This comment has been minimized.

Show comment
Hide comment
@Decstasy

Decstasy Jun 29, 2017

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

Decstasy commented Jun 29, 2017

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

@gihankarunarathne

This comment has been minimized.

Show comment
Hide comment
@davidechicco

This comment has been minimized.

Show comment
Hide comment
@davidechicco

davidechicco Jul 17, 2017

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 commented Jul 17, 2017

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!

@sw-carlin

This comment has been minimized.

Show comment
Hide comment
@sw-carlin

sw-carlin Sep 28, 2017

@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

sw-carlin commented Sep 28, 2017

@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

@ascherer

This comment has been minimized.

Show comment
Hide comment
@ascherer

ascherer Jul 21, 2018

The script works just as well with #!/bin/sh aka dash on (K)Ubuntu.

However, due to an incompatible getopt, this script fails on BSD and MacOS.

ascherer commented Jul 21, 2018

The script works just as well with #!/bin/sh aka dash on (K)Ubuntu.

However, due to an incompatible getopt, this script fails on BSD and MacOS.

@wilderfield

This comment has been minimized.

Show comment
Hide comment
@wilderfield

wilderfield Sep 10, 2018

Hey,
This actually doesn't work for me. While the variable OPTS does get appended with -- , that string does not exist in the actual command line arguments. The while loop never encounters a -- . Am I missing something?

wilderfield commented Sep 10, 2018

Hey,
This actually doesn't work for me. While the variable OPTS does get appended with -- , that string does not exist in the actual command line arguments. The while loop never encounters a -- . Am I missing something?

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