Tests#
To make full use of conditionals a wide range of tests is helpful. Traditionally there have been two programs test
(/usr/bin/test
) and [
(/usr/bin/[
) which take arguments to build test conditions and logical expressions.
[
is a weird file name to make the expressions more readable. It also expects a closing bracket as its last argument. To test, if $A
is equal to 0
, the following statements can be used:
test $A -eq 0 # Ok, 3 arguments for test
[ $A -ge 0 ] # Ok, 4 arguments for [
[$A -ge 0] # Syntax error, missing spaces
This explains the unusual syntax of the comparison operators and the necessary spaces around the brackets. Bash also provides a built-in command [[
which is very similar to [
and test
. It has more features and is easier to handle.
[[ $A -eq 0 ]] # exit code 0 iff $A is equal to 0
Test operations#
Numerical comparison#
The following table list comparison operators for integer values. It important to note that [[
interprets empty strings a numerical value 0. For example [[ $A -eq 0 ]]
with A
undefined has exit code 0, while [ $A -eq 0 ]
yields an syntax error. Variables do not have to be declared as integers (decalre -i
) for these test to work, they just have to valid string representations for integers, e.g. A=10
, B=-12
, C=013
, … Otherwise [[
exits with an error and an exit code other than 0 or 1.
Operator |
Math |
Meaning |
---|---|---|
|
\(>\) |
Greater than |
|
\(\geq \) |
Greater or equal |
|
\(<\) |
Less than |
|
\(\leq\) |
Less or equal |
|
\(=\) |
Equal to |
|
\(\neq\) |
Not equal to |
Note
Comparison of floating point numbers is seldom used and much more complicated. And extra tools like bc
(basic calculator) have to be used. For example, testing $A
\(\geq\) $B
with floating point numbers is achieved by:
(( $(echo "$A >= $B" | bc) ))
String comparison#
The following table list the string comparison operators for [[
. Instead of =
, also ==
can be used to be more in line with most other programming languages.
Operator |
Meaning |
---|---|
|
Lexicographical less than |
|
Lexicographical greater than |
|
Equal to, the right hand side can contain bash wild cards |
|
Equal to, the right hand side can be a regular expression |
|
Not equal to |
All comparisons are case-sensitive. And the lexicographical order may depend on the environment (LC_COLLATE
).
The equality test =
(or ==
) accepts shell wildcards on the right hand size, e.g. *
or ?
. In particular they have to be escaped (on the rhs) for literal matches, e.g.
[[ $A = foo\? ]]
is true only for A=foo?
, while [[ $A = foo? ]]
evaluates to true for A=foo?
or A=food
.
The =~
is similar but accepts regular expressions on the right hand size.
[[ $A =~ ^foo.$ ]]
is true for all values of A
starting with foo
followed by exactly one other character.
File tests#
Often it useful to check if a file exits or its attributes, [[
implements some file tests. All operators in the following table are unary operators, i.e. just take one argument.
Operator |
Meaning |
---|---|
|
File or directory exists |
|
File exists and is non-empty |
|
File is executable |
|
File is a regular file |
For example [[ -x my_script.sh ]]
has exit code 0 if and only if my_script.sh
exists and is executable. A common bash idiom is to check if a file to executable before actually executing it: [[ -x foo.sh ]] && ./foo.sh
.
Boolean operators#
To build more complex expressions, simpler ones can be combined by boolean operations. All these are dedicated shell built-ins and treat exit code 0 as “true” and everything else as “false”. However [[
does implement them as well, so they can be used inside and outside of [[
-expressions. It is better to use them inside since this makes grouped conditions easier to write and read. As usual “not” has a higher precedence than “and”, which has higher precedence then “or”:
Operator |
Math |
Meaning |
---|---|---|
|
\(\lor\) |
(non-exclusive) Or |
|
\(\land\) |
And |
|
\(\neg\) |
Negation |
Example: Both of the following expression evaluate to true, if A
is not 1 and between 10 and 20, i.e. \( \neg (A=1) \land ( A \ge 10 \lor A \le 20)\):
[[ ! $A -eq 1 && ( $A -ge 10 || $A -le 20 ) ]]
! [[ $A -ne 1 ]] && ( [[ $A -ge 10 ]] || [[ $A -le 20 ]] )