Home > other >  How do I iterate over bash script flags and use them?
How do I iterate over bash script flags and use them?

Time:01-13

I have a code that I wrap with a bash script, and I want to know if a certain flag was given (-b), and if so, to update some variable I have in the script (called "x"). Unfortunately, I need this to be done on the bash script, and the synthax here drives me nuts. A small example of what I did is (without the call to the code I wrap):

#!/bin/bash
x=0

while getopts :b opt; do
  case $opt in
    b) x=1;;
    ?) echo "";;
  esac
done

echo "x is ${x}"

My problem is with having more than one flag I want to pass to the command line. I tried to use: while getopts :b:f:c opt; do..., but it looks like it fails to work when I do not give the flags in the -b -f ... -c ... order (I get x is 0 when I expect it to be x is 1).

Moreover, this does not work when I want to give flags with the -- prefix (--frame instead of -f).

What should be the code for this purpose? I tried a few options but I do not manage to figure out what should the synthax exactly.

Thank you in advance.

CodePudding user response:

TL;DR

Options with argument have a colon after their character in the optstring. So getopts :b:c:f means:

  • you have a -b option that takes an argument (b:)
  • you have a -c option that takes an argument (c:)
  • you have a -f option that takes no argument (f)
  • use silent error reporting (the leading colon)

If you use while getopts :b:f:c opt; do... in your script and you type:

./script.sh -c -b -f

-b is considered as the argument of option -c, not as an option itself.

Details

Considering this part of your question: "it looks like it fails to work when I do not give the flags in the -b -f ... -c ... order", let's assume you want the b option to have no argument, and the f and c options to have one.

If your option has no argument don't put a colon after it in the optstring parameter; else put the colon after the option character. With your simple example you could try:

#!/bin/bash
x=0
fopt=""
copt=""

while getopts bf:c: opt; do
  case "$opt" in
    b) x=1;;
    f) echo "f option found"; fopt="$OPTARG";;
    c) echo "c option found"; copt="$OPTARG";;
    ?) echo "";;
  esac
done

echo "x is ${x}"
echo "fopt is ${fopt}"
echo "copt is ${copt}"

And then:

$ ./script.sh -b -c foo -f bar
c option found
f option found
x is 1
fopt is bar
copt is foo
$ ./script.sh -c foo -f bar
c option found
f option found
x is 0
fopt is bar
copt is foo
$ ./script.sh -c foo -b
c option found
x is 1
fopt is 
copt is foo

But be careful: with the last example, if you omit the foo argument of the -c option:

./script.sh -c -b
c option found
x is 0
fopt is 
copt is -b

See? -b became the missing argument and has not been considered as an option. Is it the cause of your problem?

Note: If you want to also use long options don't use the bash getopts builtin, use the getopt utility.

  •  Tags:  
  • Related