How to parse optional flags regardless of their position in script call and number of repetitions?

StackOverflow https://stackoverflow.com/questions/23290215

Domanda

I am writing a BASH script called stat which needs to parse its arguments in a way that it catches repetitions and different positions. The script can be called without any arguments, with an optional flag -r and optional filename also passed to the script as an argument, in this example directory1.

How can I parse the arguments so the following script calls are valid?

./stat
./stat -r
./stat directory1
./stat -r directory1
./stat directory1 -r
./stat directory1 -r -r
./stat -r directory1 -r

So far, I have a way to parse ./stat -r directory1.

recursive=0
while getopts ":r" opt; do
case $opt in
    r)
        recursive=1 
    ;;
    *)
                    echo "-$0: $opt is not a valid argument!"
        exit 1
    ;;
esac
done

This leaves me with parsing the directory name, which outputs only the directory name.

shift $((OPTIND-1)) #which removes processed options
echo "$*"

However, if I call the script with ./stat directory1 -r, ./stat -r directory1 -r or ./stat directory1 -r -r, the arguments are not properly parsed as the -r flag following the directory name is left out, not parsed and not removed with the shift $((OPTIND-1)) call.

So, I would like to know, how I can parse option flags so even redundant ones are captured along with the ones that may follow directory1.

Thank you for any help!

È stato utile?

Soluzione

As you've found, getopts stops at the first non-option word. You're forced to iterate over all the arguments:

dir="some default"
recursive=false
for arg; do
    if [[ $arg == "-r" ]]; then
        recursive=true
    else
        dir=$arg
    fi
done

An advantage to using "true" and "false" like this is you can then write this, since true and false are programs on the $PATH:

if $recursive; then
    do_something_repeatedly
else
    do_something_once
fi

Checking for invalid options:

for arg; do
    case $arg in
        -r) recursive=true ;;
        -*) echo "invalid option: $arg" ;;
        *)  dir=$arg ;;
    esac
done
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top