Search code examples
bashfunctiongetopts

Using getopts inside a Bash function


I'd like to use getopts inside a function that I have defined in my .bash_profile. The idea is I'd like to pass in some flags to this function to alter its behavior.

Here's the code:

function t() {
    echo $*
    getopts "a:" OPTION
    echo $OPTION
    echo $OPTARG
}

When I invoke it like this:

t -a bc

I get this output:

-a bc
?
 

What's wrong? I'd like to get the value bc without manually shifting and parsing. How do I use getopts correctly inside a function?

EDIT: corrected my code snippet to try $OPTARG, to no avail

EDIT #2: OK turns out the code is fine, my shell was somehow messed up. Opening a new window solved it. The arg value was indeed in $OPTARG.


Solution

  • As @Ansgar points out, the argument to your option is stored in ${OPTARG}, but this is not the only thing to watch out for when using getopts inside a function. You also need to make sure that ${OPTIND} is local to the function by either unsetting it or declaring it local, otherwise you will encounter unexpected behaviour when invoking the function multiple times.

    t.sh:

    #!/bin/bash
    
    foo()
    {
        foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; }
    
        local OPTIND o a
        while getopts ":a:" o; do
            case "${o}" in
                a)
                    a="${OPTARG}"
                    ;;
                *)
                    foo_usage
                    ;;
            esac
        done
        shift $((OPTIND-1))
    
        echo "a: [${a}], non-option arguments: $*"
    }
    
    foo
    foo -a bc bar quux
    foo -x
    

    Example run:

    $ ./t.sh
    a: [], non-option arguments:
    a: [bc], non-option arguments: bar quux
    foo: [-a <arg>]
    

    If you comment out # local OPTIND, this is what you get instead:

    $ ./t.sh
    a: [], non-option arguments:
    a: [bc], non-option arguments: bar quux
    a: [bc], non-option arguments:
    

    Other than that, its usage is the same as when used outside of a function.