1

Can someone explain how to perform Boolean operations and store them in variables in Bash?

I tried:

A=true
B=false
C=!$A
D=$A && $B
echo $C
echo $D

I also tried without dollars, with [], with {}, ()... How can one do such a simple operation in bash?

result in console are:

!true
true

It seems they are always treated as strings.

1
  • P.S. more or less 1st time I use bash ...
    – SheppLogan
    Commented Oct 19, 2017 at 15:25

3 Answers 3

4

Unfortunately, bash does not support boolean variables in a proper meaning. There is no "true" and "false" constants as in programming languages. Instead, /bin/true and /bin/false are two executables that don't do anything except return exit status 0 or 1. Contrary to common logic, exit status 0 is a synonim for "true" and 1 is a synonim for "false". The closest you can get to evaluating boolean expressions is either

  • [[ expr ]] which returns a exit status 0 or 1 depending on evaluating expr
  • && and || (these are conditionals depending on last command's exit status)
  • [ which is actually an executable with a silly name (not part of bash) that supports some basic expressions
  • if...elif..else..fi which you can use to your advantage to manipulate variables within the workflow
1
  • 2
    It's less of a contradiction if you think of 0 as success and non-zero as failure, rather than logical truth. [ is indeed a silly name; it's "real" name is test. (bash does additionally implement [/test internally for performance reasons, though.)
    – chepner
    Commented Oct 19, 2017 at 15:55
4

You deduced right, bash variables by default contain strings, and its values are treated as strings.

You can use the declare built-in command to explicitly say they store integers (declare -i myintvar), or indexed arrays (declare -a myarr), or associative arrays (declare -A mymap), etc., but not booleans.

The closest you can get to booleans is to use integer values 0 and 1 and evaluate expressions as arithmetic expressions with the (( expr )) command (bash-specific), or with arithmetic expansion $(( expr )) (POSIX-compatible). Those commands evaluate expr according to rules of shell arithmetic.

For example:

A=1
B=0
(( C = \!A ))       # logical negation  ==>  C = 0
(( D = A && B ))    # logical AND       ==>  D = 0
E=$(( A ^ B ))      # bitwise XOR       ==>  E = 1

In bash, you can also use declare -i and let:

declare -i E='A||B'    # equivalent to: E=$((A||B)), or ((E=A||B))
let C='!A'             # equivalent to: C=$((\!A)), or ((C=\!A))

which are a longer way of saying ((..)) or $((..)). They both force arithmetic evaluation of the expressions given.

Note that ! has a special meaning in most shells (including bash), it causes history expansion. To prevent it, we must escape it with a backslash, or quote it.

4
  • I would avoid the integer attribute; it's doesn't really provide any value. Your declare command doesn't do what you think; || is treated as the normal shell operator, so B is only executed if declare -i E=A fails. You need to quote the value: declare -i E="A||B" to have the intended effect of simulating E=$((A||B)).
    – chepner
    Commented Oct 19, 2017 at 16:00
  • Thanks, I missed the quotes there. Note that declare -i evaluates the expr as arithmetic.
    – randomir
    Commented Oct 19, 2017 at 16:06
  • So does E=$((A || B)), which is more explicit as well as being standard.
    – chepner
    Commented Oct 19, 2017 at 16:09
  • @chepner, I've updated my answer a little bit, hope the bash/posix difference is clearer now. Thanks.
    – randomir
    Commented Oct 19, 2017 at 18:31
0

like this?

t=true
f=false

# if $t; then echo Hi; fi
Hi
# if $f; then echo Hi; fi
# if ! $f; then echo Hi; fi
Hi
# if ! ($t && $t); then echo Hi; fi
# if  ($t && $t); then echo Hi; fi
Hi
0

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