test / [ ] / [[ ]]
The test command (or its equivalents [ ] and [[ ]]) evaluates a condition and returns the result as an exit status. It is widely used in if statements and while conditions to check file existence, file attributes, and to compare strings or numbers.
Syntax
Use the test command (POSIX-compliant).
test condition
Use [ ] (alternative notation for test).
[ condition ]
Use [[ ]] (Bash extension — recommended).
[[ condition ]]
Condition Expressions
| Expression | Description |
|---|---|
| -e path | True if the file or directory exists. |
| -f path | True if a regular file exists. |
| -d path | True if a directory exists. |
| -r path | True if the path is readable. |
| -w path | True if the path is writable. |
| -x path | True if the path is executable. |
| -s path | True if the file size is greater than zero. |
| -L path | True if the path is a symbolic link. |
| -z "$str" | True if the string length is zero (empty string). |
| -n "$str" | True if the string length is greater than zero. |
| "$a" = "$b" | True if strings a and b are equal (in [ ] use =; in [[ ]], == is also accepted). |
| "$a" != "$b" | True if strings a and b differ. |
| $a -eq $b | True if integers a and b are equal. |
| $a -ne $b | True if integers a and b differ. |
| $a -lt $b | True if a is less than b (less than). |
| $a -le $b | True if a is less than or equal to b (less or equal). |
| $a -gt $b | True if a is greater than b (greater than). |
| $a -ge $b | True if a is greater than or equal to b (greater or equal). |
| ! condition | Negates the condition. |
| condition1 -a condition2 | AND inside [ ] (use && inside [[ ]]). |
| condition1 -o condition2 | OR inside [ ] (use || inside [[ ]]). |
| [[ $s =~ regex ]] | True if the string matches the regular expression ([[ ]] only). |
Sample Code
Use -f (regular file) and -d (directory) to check file attributes.
check_attr.sh
#!/bin/bash
if [ -f "/etc/hosts" ]; then
echo "/etc/hosts is a regular file"
fi
if [ -d "/tmp" ]; then
echo "/tmp is a directory"
fi
bash check_attr.sh
/etc/hosts is a regular file
/tmp is a directory
Combine -r (readable) and -s (non-empty) with &&.
check_readable.sh
if [ -r "/etc/hosts" ] && [ -s "/etc/hosts" ]; then
echo "The file is readable and not empty"
fi
bash check_readable.sh
The file is readable and not empty
Use -z to check for an empty string and -n to check for a non-empty string.
check_string.sh
name="Alice"
if [ -z "$name" ]; then
echo "Name is not set"
elif [ -n "$name" ]; then
echo "Name: $name"
fi
bash check_string.sh
Name: Alice
Use operators such as -eq, -gt, and -lt for numeric comparisons.
check_number.sh
count=5
if [ $count -eq 0 ]; then
echo "Zero"
elif [ $count -gt 0 ] && [ $count -lt 10 ]; then
echo "Between 1 and 9"
fi
bash check_number.sh
Between 1 and 9
Inside [[ ]], you can use wildcard pattern matching with ==.
check_pattern.sh
filename="report_2026.pdf"
if [[ "$filename" == *.pdf ]]; then
echo "This is a PDF file"
fi
bash check_pattern.sh
This is a PDF file
Use the =~ operator inside [[ ]] to test against a regular expression.
check_semver.sh
version="v1.2.3"
if [[ "$version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Semantic version format"
fi
bash check_semver.sh
Semantic version format
You can also use the exit status of the test command directly with &&.
test -e "/tmp" && echo "/tmp exists" /tmp exists
Notes
Spaces inside [ ] are required. Writing [ -f "$file"] without a space before the closing bracket causes an error. Always quote variables with "$var" using double quotes. Without quotes, a value containing spaces is split into multiple arguments, which leads to errors.
Be careful not to mix up the integer comparison operators (-eq -ne -lt -gt -le -ge) with the string comparison operators (= !=). Using -eq with strings produces unexpected results.
For a full overview of if statements, see if / elif / else.
If you find any errors or copyright issues, please contact us.