Bash Test Operators Reference

All [ ] and [[ ]] test operators by type — file, string, arithmetic, regex.

Searchable Bash test operator reference covering file-attribute tests (-f, -d, -nt), string emptiness (-z, -n), numeric comparison (-eq, -lt), regex matching (=~) and logical combinators, each with a working example.

What is the difference between [ ] and [[ ]]?

[ ] is the POSIX test command and treats its operands as separate words, so unquoted variables can break it. [[ ]] is a Bash keyword that parses the whole expression, supports && and || and the =~ regex operator, and does not word-split unquoted variables.

Bash test operators

Bash conditional expressions decide which branch of an if, while or && chain runs. They live inside the test command, its [ ] alias, or the more capable [[ ]] keyword. The operators fall into clear families: file-attribute tests, string emptiness checks, string and numeric comparisons, regex matching, and logical combinators. This page is a searchable, offline reference with a working example for every operator.

How it works

A test operator evaluates to a true (exit status 0) or false (non-zero) result, which the surrounding control structure uses:

  • File tests are unary operators like -f (regular file), -d (directory) and -x (executable) that inspect a path, plus binary comparisons -nt, -ot and -ef that compare two files by timestamp or inode.
  • String tests -z and -n check for an empty or non-empty value.
  • Comparison uses =/==/!= for strings and -eq, -ne, -lt, -le, -gt, -ge for integers — never mix the two.
  • Regex uses [[ s =~ re ]], available only in double brackets, storing captures in BASH_REMATCH.
  • Logical operators negate (!) or combine (&&, ||, or the legacy -a, -o).

The most important rule: prefer [[ ]] for new scripts. It avoids word-splitting surprises, supports glob and regex matching, and lets you use &&/|| inside a single test.

Tips and examples

Always quote variables in [ ] to avoid syntax errors when a value is empty or contains spaces:

if [ -z "$name" ]; then
  echo "name is empty"
fi

Combine conditions cleanly inside double brackets:

if [[ -f "$config" && -r "$config" ]]; then
  source "$config"
fi

Capture parts of a match with a regex:

if [[ "$ver" =~ ^([0-9]+)\.([0-9]+)$ ]]; then
  major=${BASH_REMATCH[1]}
  minor=${BASH_REMATCH[2]}
fi

Remember the numeric-versus-string distinction: use -eq family operators for integers and =/!= for text, or comparisons will silently give the wrong answer.