Shell Test Blocks
[
is defined by the POSIX standard and thus it’s supported by all POSIX
shells. On the other hand, although [[
is more powerful it only works with
bash, zsh and ksh.
Initially
[
was implemented as a command (/usr/bin/[
). Because of that, the expression needs to be surrounded by spaces:[ expr ]
and[[ expr ]]
.
Differences
Feature | [ ... ] old style |
[[ ... ]] new style |
Comments |
---|---|---|---|
Variable expansion | "$v" |
$v |
New style will not split the variable if it contains spaces. |
String comparison | = |
= or == |
|
!= |
!= |
||
\> and \< |
> and < |
||
Integer comparison | -ge , -le , -eq |
-gt , -lt , -eq |
No differences. |
-gt , -lt , -ne |
-gt , -lt , -eq |
||
Logical operators | Deprecated by POSIX | && and || |
See below. |
Grouping | Deprecated by POSIX | ( and ) |
See below. |
Glob matching | Not available | [[ $v == *.txt ]] |
|
Regex matching | Not available | [[ $v =~ .*\.txt ]] |
POSIX deprecates -a
, -o
, \(
and \)
. So instead of using:
if [ -f file1 -a \( "$var1" -eq 0 -i "$var2" -eq 0 \) ]; then
echo true
fi
It’s necessary to use:
if [ -f file1 ] && { [ "$var1" -eq 0 ] || [ "$var2" -eq 0 ]; }; then
echo true
fi
While that could be written in the following way with [[
:
if [[ -f file 1 && ( $var1 -eq 0 || $var2 -eq 0 ) ]]; then
echo true
fi
Besides the differences above,
[
might also lack the following operators depending on the implementation:-e
,-nt
(newer than),-ot
(older than),-ef
(exact same file) and!
(not).
Arithmetic Expansion
(( ... ))
and $(( ... ))
can be used for integer comparison and arithmetic
operations.
Examples:
# POSIX sh
i=$((j + 3))
lvcreate -L "$((24 * 1024))" -n lv99 vg99
q=$((29 / 6)) r=$((29 % 6))
if test "$((a%4))" = 0; then echo "true"; fi
# Bash
((a=$a+7)) # Add 7 to a
((a = a + 7)) # Add 7 to a. Identical to the previous command.
((a += 7)) # Add 7 to a. Identical to the previous command.
if ((a > 5)); then echo "a is more than 5"; fi
true; echo "$?" # Writes 0, because a successful command returns 0.
((10 > 6)); echo "$?" # Also 0. An arithmetic command returns 0 for true.
echo "$((10 > 6))" # Writes 1. An arithmetic expression evaluates to 1 for true.
for ((i=0, j=0; i<100; i++, j+=5)); do echo "$i"; done
Unlike
[
and[[
, expressions do not need to be surrounded by spaces with$((expr))
and((expr))
.