Search code examples
bashgetopts

Bash : Parse options after arguments with getopts


In a script which request some arguments (arg) and options (-a), I would like to let the script user the possibility to place the options where he wants in the command line.

Here is my code :

while getopts "a" opt; do
  echo "$opt"
done
shift $((OPTIND-1))

echo "all_end : $*"

With this order, I have the expected behaviour :

./test.sh -a arg
a
all_end : arg

I would like to get the same result with this order :

./test.sh arg -a
all_end : arg -a

Solution

  • The getopt command (part of the util-linux package and different from getopts) will do what you want. The bash faq has some opinions about using that, but honestly these days most systems will have the modern version of getopt.

    Consider the following example:

    #!/bin/sh
    
    options=$(getopt -o o: --long option: -- "$@")
    eval set -- "$options"
    
    while :; do
        case "$1" in
            -o|--option)
                shift
                OPTION=$1
                ;;
            --)
                shift
                break
                ;;
        esac
    
        shift
    done
    
    echo "got option: $OPTION"
    echo "remaining args are: $@"
    

    We can call this like this:

    $ ./options.sh -o foo arg1 arg2
    got option: foo
    remaining args are: arg1 arg2
    

    Or like this:

    $ ./options.sh  arg1 arg2 -o foo
    got option: foo
    remaining args are: arg1 arg2