117

I have defined the following variable:

myVar=true

now I'd like to run something along the lines of this:

if [ myVar ]
then
    echo "true"
else
    echo "false"
fi

The above code does work, but if I try to set

myVar=false

it will still output true. What might be the problem?

edit: I know I can do something of the form

if [ "$myVar" = "true" ]; then ...

but it is kinda awkward.

Thanks

Jens
  • 69,818
  • 15
  • 125
  • 179
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • See also: http://stackoverflow.com/questions/2953646/how-to-declare-and-use-boolean-variables-in-shell-script/21210966#21210966 – JG_ Jun 14 '16 at 09:20

2 Answers2

182

bash doesn't know boolean variables, nor does test (which is what gets called when you use [).

A solution would be:

if $myVar ; then ... ; fi

because true and false are commands that return 0 or 1 respectively which is what if expects.

Note that the values are "swapped". The command after if must return 0 on success while 0 means "false" in most programming languages.

SECURITY WARNING: This works because BASH expands the variable, then tries to execute the result as a command! Make sure the variable can't contain malicious code like rm -rf /

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
70

Note that the if $myVar; then ... ;fi construct has a security problem you might want to avoid with

case $myvar in
  (true)    echo "is true";;
  (false)   echo "is false";;
  (rm -rf*) echo "I just dodged a bullet";;
esac

You might also want to rethink why if [ "$myvar" = "true" ] appears awkward to you. It's a shell string comparison that beats possibly forking a process just to obtain an exit status. A fork is a heavy and expensive operation, while a string comparison is dead cheap. Think a few CPU cycles versus several thousand. My case solution is also handled without forks.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
Jens
  • 69,818
  • 15
  • 125
  • 179
  • 2
    `true` and `false` are built-in commands in most shells. Invoking them is unlikely to require a `fork()` call. – Keith Thompson Sep 22 '15 at 17:40
  • Calling `which true` in bash, zsh, ksh, dash, and fish, it seems that only zsh has `true` and `false` as built-ins. Seems like a sensible thing for shells to implement though! – Christopher Shroba Sep 13 '20 at 13:39
  • 2
    don't use `which` -- that only searches the $PATH -- use `type -a true` -- true and false are builtin to bash and ksh and dash – glenn jackman Sep 13 '20 at 20:15