How to build a conditional assignment in bash?

Bash

Bash Problem Overview


I'm looking a way to build conditional assignments in bash:

In Java it looks like this:

int variable= (condition) ? 1 : 0;

Bash Solutions


Solution 1 - Bash

If you want a way to define defaults in a shell script, use code like this:

: ${VAR:="default"}

Yes, the line begins with ':'. I use this in shell scripts so I can override variables in ENV, or use the default.

This is related because this is my most common use case for that kind of logic. ;]

Solution 2 - Bash

As per Jonathan's comment:

variable=$(( 1 == 1 ? 1 : 0 ))  
EDIT:

I revised the original answer which just echo'd the value of the condition operator, it didn't actually show any assignment.

Solution 3 - Bash

myvar="default" && [[ <some_condition_is_true> ]]  && myvar="non-default"

real examples:

DELIM="" && [[ "$APP_ENV_RESOLVED" != "" ]] && DELIM=$INNER_DELIM

The condition can be "(( ... ))" as well:

filepath=/proc/drbd && (( $# > 0 )) && filepath=$1

Solution 4 - Bash

In addition to the other more general answers (particularly as per Jonathan's comment and Kevin's more general answer [which also supports strings]) I'd like to add the following two solutions:


setting the variable to either 0 or 1 based on the condition:

(as the question's example suggests.)

The general form would read

(condition); variable=$?;

where $variable results in being either 0 or 1 and condition can be any valid conditional expression.

E.g. checking a variable ...

[[ $variableToCheck == "$othervariable, string or number to match" ]]
variable=$?

... or checking a file's existence ...

[ -f "$filepath" ]
fileExists=$?

... or checking the nummerical value of $myNumber:

(( myNumber >= 1000000000 ))
is_huge_number=$?


The advantages of this solution is that
  • it supports arbitrary conditional expressions, including strings
    (which are not supported in arithmetic expressions of Jonathan's solution)
  • that variable gets declared in any case, unlike in griffon's answer:
    [ -z "$variable" ] && variable="defaultValue"
    Which would matter in case you want to nameref it later on (e.g. from within a function).


Please note: In Bash, the special variable $? always contains the exit code of the previously executed statement (or statement block; see the man bash for more details). As such, a positive result is generally represented by the value 0, not 1 (See my comment below, thanks Assimilater for pointing it out). Thus, if the condition is true (e.g [[2 eq 2]]) then $?=0.

If instead you need 0 or 1 in your variable (e.g. to print or do mathematical calculations) then you need to employ boolean negation using a leading exclamation mark (as pointed out by GypsySpellweaver in the comments below): ( ! condition ); variable=$? or ! ( condition ); variable=$?. (However, readability in terms of what happens might be a bit less obvious.)

Another possible solution by Jonathan would be variable=$(( 1 == 1 ? 1 : 0 )) - which, however, is creating a subshell.

If you want to avoid the creation of a subshel, keep good readability or have arbitrary conditions, use one of the following solutions.


setting the variable to arbitrary values:

as it is done in most other answers, it could adapted as follows:

(condition) \
    && variable=true \
    || variable=false

e.g as in

[[ $variableToCheck == "$othervariable, string or number to match" ]] \
    && variable="$valueIfTrue" \
    || variable="$valueIfFalse"

or to get 1 in a positive check, and 0 upon failure (like in the question's example):

[[ $variableToCheck == "$othervariable, string or number to match" ]] \
    && variable=1 \
    || variable=0

(for the last example, - as already mentioned in the notes above - the same can be achieved with boolean negation using a leading exclamation mark:

[[ ! $variableToCheck == "$othervariable, string or number to match" ]]
variable=$?


The advantages of this solution is that
  • it might be considered a bit better readable than Kevin's answer
    myvar="default" && [[ <some_condition_is_true> ]] && myvar="non-default", and
  • the $valueIfTrue is conditionally evaluated only if needed,
    which would matter in case you'd do something
  • with side-effect, like
    • variable=$((i++)), or
    • { variable=$1; shift; }
  • high computation, like
    • variable=$(find / -type f -name ListOfFilesWithThisNameOnMySystem)
  • is a bit shorter than ghostdog74's answer
    (which, however is great if you have multiple conditions!)
  • does not open a subshell as in Pierre's answer
  • and as above:
  • it supports arbitrary conditional expressions, including strings
    (which are not supported in arithmetic expressions of Jonathan's solution)
  • that variable gets declared in any case, unlike in griffon's answer:
    [ -z "$variable" ] && variable="defaultValue"
    Which would matter in case you want to nameref it later on (e.g. from within a function).

Solution 5 - Bash

I wanted to do a conditional assignment with strings and I ended up with:

VAR=$([ "$MYVALUE" = "value" ] && echo "YES" || echo "NO")

Which are:

VAR=$([ condition ] && value_when_true || value_when_false)

Solution 6 - Bash

Big ups to @Demosthenex and especially @Dennis Williamson for the shortest and easiest solution I've seen. Leave it to bash to require a bunch of parentheses for a simple ternary assignment. Ahh, the 60s! And to put it all together in an example...

echo $BASHRULES;             # not defined
                             # no output
: ${BASHRULES:="SCHOOL"}     # assign the variable
echo $BASHRULES              # check it
SCHOOL                       # correct answer
: ${BASHRULES="FOREVER?"}    # notice the slightly different syntax for the conditional assignment
echo $BASHRULES              # let's see what happened!
SCHOOL                       # unchanged! (it was already defined)

I wrote that a long time ago.. these days I'd probably get more excited over a solution like...

PLATFORM=iphonesimulator
OTHERSDK=iphone && [[ $PLATFORM=~os ]]      \
                &&     OTHERSDK+=simulator  \
                ||     OTHERSDK+=os

> $OTHERSDKiphoneos

Solution 7 - Bash

another way using a case/switch

case "$variable" in
  condition) result=1 ;;
          *) result=0 ;;
esac

Solution 8 - Bash

If you want to assign a value unless variable is empty use this:

[ -z "$variable" ] && variable="defaultValue"

You can put as well, each other condition on the []

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNeuquinoView Question on Stackoverflow
Solution 1 - BashDemosthenexView Answer on Stackoverflow
Solution 2 - BashAnthony ForloneyView Answer on Stackoverflow
Solution 3 - BashKevin LittleView Answer on Stackoverflow
Solution 4 - BashMartin RüeggView Answer on Stackoverflow
Solution 5 - BashPierre MaouiView Answer on Stackoverflow
Solution 6 - BashAlex GrayView Answer on Stackoverflow
Solution 7 - Bashghostdog74View Answer on Stackoverflow
Solution 8 - Bashgriffon vultureView Answer on Stackoverflow