6

I have a script running on Linux that accepts some parameters.
I would like to do something like:

if [[ $CONDITION == "true" ]]; then  
  script param1 --param2  
else
  script param1  
fi 

I would like to avoid the forking path of the if.
Is there a more optimal way to pass the second parameter?

  • 1
    Where is this if? In the script itself? In another script that calls the target script? Are these options (--param2) or arguments (param1)? Please edit your question and give us more details. – terdon May 30 '18 at 8:17
  • One other note: true is a shell builtin that returns a success exit status. If you use CONDITION=false when CONDITION is not true, then you could write: if "$CONDITION"; then echo yes; fi or "$CONDITION" && echo yes – glenn jackman May 30 '18 at 19:21
  • @glennjackman:The true is not the same as "true" right? – Jim May 30 '18 at 20:40
  • They are the same: gnu.org/software/bash/manual/bash.html#Quote-Removal -- you can execute the command "echo" "foo" with no difficulty because the shell will remove the quotes before executing the command. – glenn jackman May 30 '18 at 20:44
  • For example I often do valid=false if someCondition; then valid=true; fi; if ! $valid; then echo Invalid; exit 1; fi – glenn jackman May 30 '18 at 20:47
18

The most expansible and robust way would probably be to use an array to hold the optional parameter(s):

params=()
if [[ $CONDITION == true ]]; then
    params+=(--param2)
fi
script param1 "${params[@]}"

Or in shorthand:

[[ $CONDITION == true ]] && params+=(--param2)
script param1 "${params[@]}"

That avoids repeating the constant part of the command and you can put more than one argument in the array, even the whole command.

Note that it's important to do this with an array: if you replace the array with a regular variable (params="--param2"; script param1 $params) you'll either have to expand the variable unquoted, with all the problems that brings, or expand it quoted, in which case you'll pass an empty string as argument if the variable is empty.

In a simple case like this, the "alternate value" expansion can also be used:

cond=x
p2="--param2"
script param1 ${cond:+"$p2"}

Here, if cond is nonempty (regardless of if it's cond=false or cond=0 instead of cond=true), the value of p2 is expanded. This may be seen as less ugly than arrays, but be careful with the placement of the quotes.

See also:

| improve this answer | |
  • it should be noted that this is passing in part the literal string --, and not the unary -- operator – Steven Penny May 30 '18 at 18:22
  • 1
    @StevenPenny, well, the whole idea of a -- operator only exists in the shell within arithmetic expansions, and there aren't any here. I can't think of any special meaning for the dash in the shell outside of them, either. – ilkkachu May 30 '18 at 18:39
  • @ilkkachu how can you do this in one line? script param1 ${[[ $CONDITION == true ]] && params+=(--param2)} ? – Turnipdabeets Apr 15 at 16:37
  • @Turnipdabeets, do you mean something like this? par="x y"; printf ":%s\n" a b ${par+"$par"} It should expand par as another argument after b, if par is set (i.e. unset par; printf ":%s\n" a b ${par+"$par"} there would not be an empty argument after b). Or you could have ${cond:+"$par"} to expand par if cond is non-empty. – ilkkachu Apr 17 at 17:40
5

A versatile way to do this is to set the arguments in an array. The most basic array is the list of positional parameters defined with set. You can build the list of parameters in sequence.

set -- param1
if [[ $CONDITION == "true" ]]; then  
    set -- "$@" --param2  
fi 

command "$@"  

Which could be reduced to:

set -- param1
[[ $CONDITION == "true" ]] && set -- "$@" --param2
command "$@"  

If the list of positional parameters needs to be preserved, then either:

  • Use a function:

    callcommand(){     set -- param1
                       [[ $CONDITION == "true" ]] && set -- "$@" --param2
                       command "$@"       
                 }
    callcommand
    
  • Or use some other array variable:

    paramArray=()
    paramArray+=(param1)
    [[ $CONDITION == "true" ]] && paramArray+=( "--param2" )
    command "${paramArray[@]}"
    
| improve this answer | |
  • I don't really understand this. param1 is already a parameter. Does this change the parameter array of the script? – Jim May 31 '18 at 20:48
  • @Jim No, param1 is not an argument of the script code above, it become a parameter of the command called. Yes, the positional parameters are changed (as they are used). See some alternatives in the edited answer. – Isaac Jun 1 '18 at 6:53
-1
PARAMS+=" param1"
if [[ $CONDITION == "true" ]]; then  
  PARAMS+=" --param2"
fi
script ${PARAMS}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.