One of the tricky things about bash and other Bourne-derived shells is that a condition used in an if
or while
statement is not an expression. It's a command, and the condition is treated as true or false depending on whether the command succeeded or failed. A command indicates success by returning an exit status of 0, and failure by returning anything else.
The built-in commands true
and false
do nothing other than returning an exit status denoting success or failure, respectively.
The [ ... ]
and [[ ... ]]
constructs can be used to simulate using an expression as a condition. [
is actually a command, very nearly equivalent to the test
command.
If I need the equivalent of a Boolean variable in a bash script, I use a variable whose value is either the string true
or the string false
. If I use that variable as a condition, it expands to the command name true
or false
. I just have to be careful to ensure that such a variable never takes some value other than true
or false
.
And it's important to remember not to use the [ ... ]
syntax. With a single argument, for example
if [ false ] ; then # This is incorrect!
the command succeeds because false
is a non-empty string. Remember that the [
and ]
are not part of the syntax of an if
statement (though they're designed to look like they are).
An example:
#!/bin/bash
func() {
if $1 ; then
echo In func, the condition is true
else
echo In func, the condition is false
fi
}
func false
func true
The output:
In func, the condition is false
In func, the condition is true
This technique does have some drawbacks. It can break if you assign a value other than exactly true
or false
to a variable, or even if you misspell the name of a variable. And unlike in languages with a built-in Boolean type and false
and true
literals, the shell is likely to fail to diagnose such errors, causing your script to silently misbehave.