Shell Script Arguments – How to Parse Optional Arguments in Bash Script Without Order

argumentsshell-script

I'm confused how to include optional arguments/flags when writing a bash script for the following program:

The program requires two arguments:

run_program --flag1 <value> --flag2 <value>

However, there are several optional flags:

run_program --flag1 <value> --flag2 <value> --optflag1 <value> --optflag2 <value> --optflag3 <value> --optflag4 <value> --optflag5 <value> 

I would like to run the bash script such that it takes user arguments. If users only input two arguments in order, then it would be:

#!/bin/sh

run_program --flag1 $1 --flag2 $2

But what if any of the optional arguments are included? I would think it would be

if [ --optflag1 "$3" ]; then
    run_program --flag1 $1 --flag2 $2 --optflag1 $3
fi

But what if $4 is given but not $3?

Best Answer

This article shows two different ways - shift and getopts (and discusses the advantages and disadvantages of the two approaches).

With shift your script looks at $1, decides what action to take, and then executes shift, moving $2 to $1, $3 to $2, etc.

For example:

while :; do
    case $1 in
        -a|--flag1) flag1="SET"            
        ;;
        -b|--flag2) flag2="SET"            
        ;;
        -c|--optflag1) optflag1="SET"            
        ;;
        -d|--optflag2) optflag2="SET"            
        ;;
        -e|--optflag3) optflag3="SET"            
        ;;
        *) break
    esac
    shift
done

With getopts you define the (short) options in the while expression:

while getopts abcde opt; do
    case $opt in
        a) flag1="SET"
        ;;
        b) flag2="SET"
        ;;
        c) optflag1="SET"
        ;;
        d) optflag2="SET"
        ;;
        e) optflag3="SET"
        ;;
    esac
done

Obviously, these are just code-snippets, and I've left out validation - checking that the mandatory args flag1 and flag2 are set, etc.

Which approach you use is to some extent a matter of taste - how portable you want your script to be, whether you can live with short (POSIX) options only or whether you want long (GNU) options, etc.

Related Question