2

I have a bash script and I want to use it to pass an optional parameter with spaces to another script. My script (pass_optional_arg.sh) looks like:

#!/usr/bin/env bash

mandatory_arg=${1}

if [[ -z ${mandatory_arg} ]]
then
  echo "Mandatory arg missing"
  exit 1
fi

optional_arg=${2}

./echo_args.sh ${mandatory_arg} an_irrelevant_arg  "${optional_arg}"

Script echo_args.sh just prints the arguments in single quotes, as well as their number:

#!/usr/bin/env bash

echo "Number of args: ${#}"
for var in "${@}"
do
    echo "Arg: '"${var}"'"
done

Output of running ./pass_optional_arg.sh a_mandatory_arg 'an arg with spaces'

Number of args: 3

Arg: 'a_mandatory_arg'

Arg: 'an_irrelevant_arg'

Arg: 'an arg with spaces'

Which is exactly what I want. However, if I run without providing the optional argument: ./pass_optional_arg.sh a_mandatory_arg

Number of args: 3

Arg: 'a_mandatory_arg'

Arg: 'an_irrelevant_arg'

Arg: ''

In this case I want the arguments to be 2, and not an empty arg at the end.

If I change the last line of pass_optional_arg.sh to remove the quotes from the optional arg ./echo_args.sh ${mandatory_arg} an_irrelevant_arg ${optional_arg}

then the second case is fixed but the first breaks: ./pass_optional_arg.sh a_mandatory_arg 'an arg with spaces'

Number of args: 6

Arg: 'a_mandatory_arg'

Arg: 'an_irrelevant_arg'

Arg: 'an'

Arg: 'arg'

Arg: 'with'

Arg: 'spaces'

Of course, I could satisfy both cases with an if statement

if [[ -z ${optional_arg} ]]
then
  ./echo_args.sh ${mandatory_arg} an_irrelevant_arg
else
  ./echo_args.sh ${mandatory_arg} an_irrelevant_arg  "${optional_arg}"
fi

This may be fine for a small command like this, but cannot scale for several optional arguments. Also for a command that is very complicated and long, having to duplicate it like this is not ideal. Any way to make this work without the above if statement?

I found several questions about optional parameters OR parameters with spaces, like this, this and this, but I could not find what I am asking for in any of them.

Community
  • 1
  • 1
PetrosP
  • 635
  • 6
  • 15

1 Answers1

1

You'll need a conditional somewhere, because "..." is always going to be a distinct argument, even if the ... is empty. By the way, you absolutely want to quote all the parameter expansions:

./echo_args.sh "${mandatory_arg}" an_irrelevant_arg "${optional_arg}"

You might want to use an array instead:

mandatory_arg=${1}

# Check $# directly; just because $1 is empty doesn't mean it is *missing*
if (( $# < 1 ))
then
  echo "Mandatory arg missing"
  exit 1
fi
# Or simply
# mandatory_arg=${1:?Mandatory arg missing}

args=( "$mandatory_arg" an_irrelevant_arg )
(( $# >= 2 )) && args+=("$2")

./echo_args.sh "${args[@]}"
chepner
  • 497,756
  • 71
  • 530
  • 681