10

Can getopts be used to pick up whole-word flags?

Something as follows:

while getopts ":abc --word" opt; do
    case ${opt} in
        a) SOMETHING
            ;;
        ...
        --word) echo "Do something else."
            ;;
    esac
done

Trying to pick up those double-dash flags.

kid_x
  • 1,415
  • 1
  • 11
  • 31

3 Answers3

9

Basically Ark's answer but easier and quicker to read than the mywiki page:

#!/bin/bash
# example_args.sh

while [ $# -gt 0 ] ; do
  case $1 in
    -s | --state) S="$2" ;;
    -u | --user) U="$2" ;;
    -a | --aarg) A="$2" ;;
    -b | --barg) B="$2" ;;

  esac
  shift
done

echo $S $U, $A $B

$# represents the number of arguments, -gt is "greater than", $1 is the flag in this case, and $2 is the flag's value.

./example_args.sh --state IAM --user Yeezy -a Do --barg it results in:

IAM Yeezy, Do it
jestrabikr
  • 420
  • 5
  • 12
Keenan
  • 399
  • 3
  • 6
  • If you want to validate the arguments using something like `*) echo "Unknown argument '$1'."; exit 1 ;;`, make sure you use `shift` with the arguments that need a passed value: `-a | --aarg) A="$2"; shift ;;` – Ken Feb 21 '22 at 12:26
  • Using the same code as yours but if I don't pass any arguments to the script inside the while loop `$#` is always looping between 1 and 2. I can't figure out why this happening :( – Sunlight Jul 01 '22 at 02:53
  • just use an if statement before the while. check [ $# -eq 0 ] to see if there are exactly 0 arguments. then you can print out an error and exit 1, so the script would never get to the while loop – clockw0rk Feb 16 '23 at 00:49
  • also isn't the first default argument always script name or something? is this of importance here? – clockw0rk Feb 16 '23 at 00:49
6

http://mywiki.wooledge.org/BashFAQ/035 Credit goes to: How can I use long options with the Bash getopts builtin?.

Community
  • 1
  • 1
4rk
  • 375
  • 3
  • 15
  • Thanks. Found a possible workaround by including "-:" in the optstring. Wondering what the pitfalls to this approach might be. – kid_x Feb 25 '14 at 21:01
3

Found one way to do this:

while getopts ":abc-:" opt; do
    case ${opt} in
        a) echo "Do something"
            ;;
        ...
        -)
            case ${OPTARG} in
                "word"*) echo "This works"
                    ;;
            esac
    esac
done

By adding -: to the opstring and adding a sub-case using $OPTARG, you can pick up the long option you want. If you want to include an argument for that option, you can add * or =* to the case and pick up the argument.

kid_x
  • 1,415
  • 1
  • 11
  • 31
  • Pity that this requires the word flags to be prefixed with a double dash. How can I achieve e.g. GCC's `-rdynamic` ? – user2023370 Jun 01 '15 at 21:07
  • This method only works for a single longer argument. Any extra multi-char argument is not parsed. – JoepBC Jul 07 '23 at 12:46
  • Ah true. I think there's probably a modification that allows for more than one multi-char args. Haven't thought about it in a long time, but I can offer an edit once I resolve it. – kid_x Jul 10 '23 at 22:21