testing
[[ ]]
Bash-specific conditional expression with safer parsing, glob and regex matching, and short-circuit logical operators. No word splitting or filename expansion happens on the arguments, so quoting is far less error-prone than [ ] — but [[ ]] is not POSIX.
[[ EXPR ]] Common flags / operators
| Flag / Operator | Purpose |
|---|---|
| == != | String compare; RHS is a glob unless quoted |
| =~ | Regex match — captures land in ${BASH_REMATCH[@]} |
| && || | Logical AND / OR (inside [[ ]]) |
| < > | Lexicographic string compare (no escaping needed) |
| -v NAME | True if variable NAME is set (even to empty) |
| file tests | -f / -d / -e / -r / -w / -x work as in [ ] |
Examples
[[ $file == *.log ]] && echo log Glob match — no need to quote RHS.
[[ $email =~ ^[a-z]+@[a-z]+\.[a-z]+$ ]] Regex match; matched groups in ${BASH_REMATCH[1]}...
[[ -n $var && $var != skip ]] Chained conditions using && inside [[ ]].
[[ -v CONFIG ]] True if CONFIG is set — distinguishes unset from empty.
Gotcha
Quoting the RHS of == turns off glob matching: [[ $x == 'a*' ]] tests literal 'a*'. [[ ]] is NOT POSIX — scripts starting with '#!/bin/sh' should stick to [ ].
Related
test / [ ]
POSIX conditional expression evaluator — tests file attributes, string comparisons, and integer comparisons, returning exit status 0 (true) or 1 (false). [ is a command (with a required closing ]), not syntax — arguments must be separated by spaces.
(( )) arithmetic
Bash arithmetic evaluation — treats operands as integers and supports C-style operators (+, -, *, /, %, **, <<, >>, &, |, ^, &&, ||, !, ==, !=, <, >, ternary). (( )) returns exit status 0 if EXPR is non-zero, 1 if zero; $(( )) substitutes the result as a string.
if / then / elif / else / fi
Conditional branching based on the exit status of a command (0 = true, non-zero = false). Runs the then-branch when the tested command succeeds; supports optional elif and else clauses and must be terminated with fi.