miken32
miken32

Reputation: 42762

Optionally passing arguments to commands in a script

I've got a shell script with a section like this:

if [ "$condition" -eq 1 ]; then
    external_command -argument value1
else
    external_command -argument value1 -second_argument value2
fi

I was bugged by this repetition, so I tried this:

arg="-second_argument"
val="value2"
if [ "$condition" -eq 1 ]; then
    arg=""
    val=""
fi
external_command -argument value1 "$arg" "$val"

It didn't work because the external_command still gets the empty strings as distinct arguments and complains.

Is there a way to do this without building the command line repeatedly? In my actual code there are 4 different conditions, so there's a lot of needless repetition.

If I were using Bash, I'd follow Bash FAQ 050 and build an array for the command arguments, but I'm not.

Upvotes: 1

Views: 127

Answers (3)

Charles Duffy
Charles Duffy

Reputation: 295934

If you populate a variable whenever the second condition should be given, and leave it unset otherwise, you have another POSIX-compliant option:

# have a variable set ONLY IF you want the extra arguments passed
if [ "$condition" -eq 1 ]; then
  unset want_extra_args
else
  want_extra_args=1
fi

# and put those arguments in a ${var+val} expansion
external_command -argument value1 ${want_extra_args+-second_argument value2}

You can use quotes and other expansions -- which is to say, the following is valid:

external_command ... ${want_extra_args+-second_argument "$value2"}

Upvotes: 1

chepner
chepner

Reputation: 532418

The standard workaround is to use the positional parameters in place of an array. Assuming you don't care about the current values:

shift $#  # Clear them; optional, as the next line overwrites whatever was there
set -- -argument value1
if [ "$condition" -eq 1 ]; then
  set -- "$@" "-second_argument"  "value2"
fi
external_command "$@"

If you do care about the current values, run the block in a subshell:

(
  set -- -argument value1
  if [ "$condition" -eq 1 ]; then
    set -- "$@" "-second_argument"  "value2"
  fi
  external_command "$@"
)

Or, define a function, which already has its own set of positional parameters.

run_external () {
  condition=$1
  set -- -argument value1
  if [ "$condition" -eq 1 ]; then
    set -- "$@" -second_argument value2
  fi
  external_command "$@"
}

run_external "$condition"

Upvotes: 2

torbatamas
torbatamas

Reputation: 1296

Just try

second=
if [ "$condition" -ne 1 ]; then
    second="-second_argument value2"
fi
external_command -argument value1 $second

Note the double quotes / absence of them. Although user1934428 is right, if you have spaces in value of -second_argument, you might have problems.

Upvotes: -1

Related Questions