Page 1 of 1

[SOLVED] Parse for command line options using enhanced getopt

Posted: Sun Aug 18, 2019 4:01 am
by kwyrky
I found a nice example script here which is a little demo on how to parse for command line options (on this page search for the answer which has "enhanced getopt" in it by Robert Siemer): https://stackoverflow.com/questions/192 ... ts-in-bash

I tried to modify it for my needs so instead of one I have two parameters which take an option...

Code: Select all

#!/bin/bash

############################################################################################################
#COMMAND LINE OPTIONS
############################################################################################################

# saner programming env: these switches turn some bugs into errors
set -o errexit -o pipefail -o noclobber -o nounset

# -allow a command to fail with !’s side effect on errexit
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
! getopt --test > /dev/null 
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
    echo 'I’m sorry, `getopt --test` failed in this environment.'
    exit 1
fi

OPTIONS=dfku:v
LONGOPTS=debug,force,keyfile,uuid:,verbose

# -regarding ! and PIPESTATUS see above
# -temporarily store output to be able to check for errors
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
# -pass arguments only via   -- "$@"   to separate them correctly
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
    # e.g. return value is 1
    #  then getopt has complained about wrong arguments to stdout
    exit 2
fi
# read getopt’s output this way to handle the quoting right:
eval set -- "$PARSED"

# set defaults
d=n 
f=n 
v=n 
keyfile=
uuid=

# now enjoy the options in order and nicely split until we see --
while true; do
    case "$1" in
        -d|--debug)
            d=y
            shift
            ;;
        -f|--force)
            f=y
            shift
            ;;
        -v|--verbose)
            v=y
            shift
            ;;
        -k|--keyfile)
            keyfile="$2"
            shift 2
            ;;
        -u|--uuid)
            uuid="$2"
            shift 2
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "Programming error"
            exit 3
            ;;
    esac
done

echo "verbose: $v, force: $f, debug: $d, keyfile: $keyfile, uuid: $uuid" 
if I run the script with

Code: Select all

./script -d -f -v -u myuuid
it works and I get

Code: Select all

verbose: y, force: y, debug: y, keyfile: , uuid: myuuid
but if I run it with setting parameter k like

Code: Select all

./script -d -f -v -k mykeyfile -u myuuid
or

Code: Select all

./script -d -f -v -k mykeyfile
it prints out

Code: Select all

Programming error
so the last case is executed...

So why is that? How can I fix this?

Re: [SOLVED] Parse for command line options using enhanced getopt

Posted: Sun Aug 18, 2019 6:18 am
by kwyrky
Ok after reading about getopt I found out I had to put another double colon ":" next to the parameter k / keyfile because this tells getopt that this parameter requires an argument, which is true in this case. It should look like this:

Code: Select all

...
OPTIONS=dfk:u:v
LONGOPTS=debug,force,keyfile:,uuid:,verbose
...