0

I tried the code in this SO post - How to evaluate a boolean variable in an if block in bash? and it does not work. It looks like there are no booleans in BASH. Is there a flawless workaround which lets me set and check booleans in BASH ?

My code -

#!/bin/bash
flag=true
if [ $flag ]
echo 'True'
#flag=false
#echo 'Now changed to false' 
fi

Even if flag=false in line 2, output is still True. Why ?

Community
  • 1
  • 1
Steam
  • 9,368
  • 27
  • 83
  • 122
  • Please see Jens answer in the link provided. if $myVar; then ... ;fi logic seems to have a security flaw. – Steam Aug 01 '13 at 22:35

3 Answers3

10

Try without square brackets, like this

#!/bin/bash
flag=true
if $flag ; then
   echo 'True'
   #flag=false
   #echo 'Now changed to false' 
fi
Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
Cristian Meneses
  • 4,013
  • 17
  • 32
  • 1
    +1 for correct answer. Note also that it's "#!", not "!#", on the first line of a script. – Ernest Friedman-Hill Aug 01 '13 at 22:25
  • What is the difference between brackets and no brackets ? – Steam Aug 01 '13 at 22:28
  • 1
    Without brackets, it attempts to execute the value as a command. It works here because the `true` command returns true, and the `false` command returns false. You can also set `flag="rm -r /*"`, and have the condition delete all your files. – that other guy Aug 01 '13 at 22:34
  • Please see Jens answer in the link provided. if $myVar; then ... ;fi logic seems to have a security flaw. – Steam Aug 01 '13 at 22:35
  • @blasto, whether it's a security issue or not depends on the script and where the value of the variable comes from. It certainly could be a problem sometimes. – Ernest Friedman-Hill Aug 01 '13 at 22:47
  • This syntax `if $var; then {...}` is not correct anyway, any empty string `var=""` will incorrectly evaluate to `true`, at least in bash. – Peter Kionga-Kamau Mar 16 '23 at 13:06
4

It evaluates to true because of this part of 'man test' -

 [ expression ]
         string        True if string is not the null string.

You need to use something like -

#!/bin/bash
flag=1
if [ ${flag} -eq 1 ]
then
    echo 'True'
    #flag=0
    #echo 'Now changed to false' 
fi
Omeganon
  • 191
  • 3
  • btw, why did you put flag in {} brackets ? cant we do "$flag" == 1 instead ? – Steam Aug 01 '13 at 22:36
  • `${flag}` and `$flag` are the same. You shouldn't use double quotes and `==` here, though, because you want to do a numeric comparison, not a string comparison. – Ansgar Wiechers Aug 01 '13 at 22:40
  • @AnsgarWiechers - thanks. but, isn't numeric and string comparison the same thing here ? We are just creating a flag and checking its state. – Steam Aug 01 '13 at 22:41
  • @blasto. I use ${} out of habit. It prevents bash from trying to interpret the contents of the variable. – Omeganon Aug 08 '13 at 22:49
0

Setting

To set a bash variable $subject to boolean true or false, use subject=true or subject=false. To set a vash variable to null, use subject= or subject=$() or unset subject

Testing

The use of single brackets and no brackets is suspicious and I've found several discrepancies in the expected behavior around how empty strings, null values, and integer 0 and 1 are evaluated.

First, defining the correct behavior of a strict boolean test as follows:

  • The if test for boolean true evaluates to true only when the subject is boolean true. Such a test will evaluate to false for any other value, including 1 and any string with value 'true'
  • The if test for false evaluates to true only when the subject is boolean false. Such a test will evaluate to false for any other value, including 0, null, and an empty string ''

The correct method to accomplish this is to use double square brackets and explicitly test against true or false as follows:

if [[ ${subject} = true ]]; then { ... } fi  # only if boolean true
if [[ ${subject} = false ]]; then { ... } fi # only if boolean false

Note that if you use such a test for boolean true (or false), an else block will not only cover the opposite condition, but also the entire set of possible values that are not boolean false (or true) respectively.

Peter Kionga-Kamau
  • 6,504
  • 2
  • 17
  • 13