Skip to content

Instantly share code, notes, and snippets.

@kaushalmodi
Created April 27, 2017 14:06
Show Gist options
  • Save kaushalmodi/74e9875d5ab0a2bc1010447f1bee5d0a to your computer and use it in GitHub Desktop.
Save kaushalmodi/74e9875d5ab0a2bc1010447f1bee5d0a to your computer and use it in GitHub Desktop.

Revisions

  1. kaushalmodi created this gist Apr 27, 2017.
    73 changes: 73 additions & 0 deletions parse_args_getopt.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    #!/usr/bin/env bash
    # Time-stamp: <2017-04-27 09:57:21 kmodi>
    #
    # Example of using getopt to parse command line options
    # http://stackoverflow.com/a/29754866/1219634 Limitation: All the options
    # starting with - have to be listed in --options/--longoptions, else getopt will
    # error out. So this cannot be used in wrapper scripts for other applications
    # where you plan to pass on the non-wrapper-script options to that wrapped
    # application.

    # Initialize variables
    help=0
    debug=0
    verbose=0
    dummy_arg="__dummy__"
    extra_args=("${dummy_arg}") # Because set -u does not allow undefined variables to be used
    discard_opts_after_doubledash=0 # 1=Discard, 0=Save opts after -- to ${extra_args}

    echo "All pre-getopt arguments: $*"

    getopt --test > /dev/null
    if [[ $? -ne 4 ]]; then
    echo "I'm sorry, 'getopt --test' failed in this environment."
    exit 1
    fi

    # An option followed by a single colon ':' means that it *needs* an argument.
    # An option followed by double colons '::' means that its argument is optional.
    # See `man getopt'.
    SHORT=hDvo: # List all the short options
    LONG=help,debug,verbose,output: # List all the long options

    # - Temporarily store output to be able to check for errors.
    # - Activate advanced mode getopt quoting e.g. via "--options".
    # - Pass arguments only via -- "$@" to separate them correctly.
    # - getopt auto-adds "--" at the end of ${PARSED}, which is then later set to
    # "$@" using the set command.
    PARSED=$(getopt --options ${SHORT} \
    --longoptions ${LONG} \
    --name "$0" \
    -- "$@") #Pass all the args to this script to getopt
    if [[ $? -ne 0 ]]; then
    # e.g. $? == 1
    # then getopt has complained about wrong arguments to stdout
    exit 2
    fi
    # Use eval with "$PARSED" to properly handle the quoting
    # The set command sets the list of arguments equal to ${PARSED}.
    eval set -- "${PARSED}"

    echo "Getopt parsed arguments: ${PARSED}"
    echo "Effective arguments: $*"
    echo "Num args: $#"

    while [[ ( ${discard_opts_after_doubledash} -eq 1 ) || ( $# -gt 0 ) ]]
    do
    echo "parsing arg: $1"
    case "$1" in
    -o|--output) shift
    out_file="$1";;
    -h|--help) help=1;;
    -D|--debug) debug=1;;
    -v|--verbose) verbose=1;;
    --) if [[ ${discard_opts_after_doubledash} -eq 1 ]]; then break; fi;;
    *) extra_args=("${extra_args[@]}" "$1");;
    esac
    shift # Expose the next argument
    done

    # Now delete the ${dummy_arg} from ${extra_args[@]} array # http://stackoverflow.com/a/16861932/1219634
    extra_args=("${extra_args[@]/${dummy_arg}}")

    echo "help: ${help}, debug: ${debug}, verbose: ${verbose}, in: $1, out: $out_file, extra args=${extra_args[*]}"