Lesson 7 / 25

Tests: [[ ]], [ ] and (( ))

Write string, numeric and file tests correctly.

How Bash decides true or false

In Bash, if runs a command and branches on its exit status: 0 is true, non-zero is false. Test commands make conditions. [ ... ] (the test command) is POSIX and works in any shell, but needs careful quoting. [[ ... ]] is a Bash keyword that is safer and more capable: no word splitting of variables inside it, && and || inside the brackets, pattern matching with == ([[ $file == *.log ]]) and regular expressions with =~ (captures in BASH_REMATCH). String tests: -z (empty), -n (non-empty), ==, !=. Numeric tests inside brackets use -eq, -ne, -lt, -le, -gt, -ge; < and > inside [[ ]] compare strings alphabetically, which is a common bug. For numbers, prefer (( ... )), an arithmetic test where (( count > 10 )) works naturally. File tests: -e exists, -f regular file, -d directory, -r/-w/-x permissions, -s non-empty, -L symlink.

Exit status drives every decision

if, while and && all branch on whether a command returned 0.

A command box emitting either a green zero badge leading to a tick path or a red non-zero badge leading to a cross path.
Figure 3.1 — Exit status as the basis of conditions.

Common tests

Strings, numbers, files and patterns.

name="report.log"
count=12

if [[ -z "$name" ]]; then echo "empty name"; fi
if [[ $name == *.log ]]; then echo "a log file"; fi
if [[ $name =~ ^([a-z]+)\.log$ ]]; then echo "base: ${BASH_REMATCH[1]}"; fi

if (( count > 10 )); then echo "more than ten"; fi
if [[ $count -ge 10 && -f /etc/hosts ]]; then echo "both true"; fi

[[ "10" < "9" ]] && echo "string compare: '10' sorts before '9'"   # trap!

if [[ -d /var/log && -r /var/log/syslog ]]; then echo "can read syslog"; fi

Use (( )) for numbers

[[ 10 > 9 ]] compares strings, and "10" sorts before "9", so the test is false. Write numeric comparisons as (( a > b )) or with -gt to avoid this trap.

Quick check: Which test correctly checks whether the number in $n is greater than 10?

  • (( n > 10 ))
  • [[ $n > 10 ]]
  • [ $n > 10 ]
  • [[ $n == >10 ]]
Answer

(( n > 10 )) — Arithmetic evaluation compares numbers; > inside [[ ]] compares strings and inside [ ] is a redirection.