0

I'm struggling with the following code.

#!/bin/bash

test-one () {
  if [[ ! -z $1 ]] ; then
    echo "You are in function test-one with arg $1"
  else
    echo "You are in function test-one with no args"
  fi
}

while getopts ":a:b:" opt; do
   case $opt in
      a) test-one ${OPTARG}
      exit;;
      b) FOO=${OPTARG}
      exit;;
   esac
done

I's just like to call the function test-one whether the optional argument is passed or not. What I am looking for is:

./script.sh -a argument1

would results in:

You are in function test-one with arg argument1

While:

./script.sh -a

would results in:

You are in function test-one with no args

Far by now the example "./script.sh -a" simply skip the function call ... What am I doing wrong? Thanks!

EBAH
  • 99
  • 9

2 Answers2

1

Regarding error-reporting, there are two modes getopts can run in:

verbose mode & silent mode

For productive scripts I recommend to use the silent mode, since everything looks more professional, when you don't see annoying standard messages. Also it's easier to handle, since the failure cases are indicated in an easier way.

Verbose Mode

invalid option VARNAME is set to ?(question-mark) and OPTARG is unset

required argument not found VARNAME is set to ?(question-mark), OPTARG is unset and an error message is printed

Silent Mode

invalid option VARNAME is set to ?(question-mark) and OPTARG is set to the (invalid) option character

required argument not found VARNAME is set to :(colon) and OPTARG contains the option-character in question

Try this:

#!/bin/bash
while getopts ":a:" opt; do
 case $opt in
   a)
       echo "-a was triggered, Parameter: $OPTARG" >&2
   ;;
  \?)
       echo "Invalid option: -$OPTARG" >&2
       exit 1
   ;;
    :) echo "Option -$OPTARG requires an argument." >&2
       exit 1
   ;;
 esac
done
wuseman
  • 1,259
  • 12
  • 20
0

When a -a is passed you will pass the value on the command line that is given as the argument to -a, stored in OPTARG. In your second example you there is no such argument, so the value gets an empty string, which is dutifully passed to the function.

Unfortunately here, a 0-length string is not preserved as an argument, and at least would in fact be a 0-length string which would "pass" the -z test.

So for "what you are doing wrong" it seems that you are expecting an empty argument to be treated as a non empty argument. You could test OPTARG before using it as an argument if you wanted to verify that -a did in fact have a value passed along with it.

Eric Renouf
  • 13,950
  • 3
  • 45
  • 67
  • Ok my mistake: I edited the question to better explain what I would like to achieve. – EBAH Dec 07 '18 at 18:13
  • 1
    @EBAH if you want to always call `test-one` call it outside the loop, store the argument as you do with `-b` and call it after you parsed the arguments – Eric Renouf Dec 07 '18 at 18:15