Skip to main content

Overview

The test command (also invoked as [) evaluates conditional expressions and returns an exit status of 0 (true) or 1 (false). It’s commonly used in conditional statements and scripts to test files, strings, and numeric values.

Syntax

test EXPRESSION
[ EXPRESSION ]
When using [, you must close it with ] and include spaces around brackets:
[ -f file.txt ]      # Correct
[-f file.txt]        # Incorrect
[  -f file.txt  ]    # Correct (extra spaces are fine)

File Test Operators

-f FILE
test
True if FILE exists and is a regular file (not a directory)
test -f config.json && echo "File exists"
-d FILE
test
True if FILE exists and is a directory
[ -d /home/user ] && echo "Directory exists"
-e FILE
test
True if FILE exists (file or directory)
test -e /tmp && echo "Path exists"

String Test Operators

-z STRING
test
True if STRING is empty (zero length)
test -z "$VAR" && echo "Variable is empty"
-n STRING
test
True if STRING is not empty (non-zero length)
[ -n "$VAR" ] && echo "Variable is set"
STRING1 = STRING2
test
True if strings are equal
test "$USER" = "alice" && echo "Hello Alice"
STRING1 == STRING2
test
Alternative syntax for string equality (same as =)
[ "$SHELL" == "nash" ] && echo "Running Nash"
STRING1 != STRING2
test
True if strings are not equal
test "$ENV" != "production" && echo "Not production"

Numeric Comparison Operators

NUM1 -eq NUM2
test
True if numbers are equal
[ "$COUNT" -eq 10 ] && echo "Count is 10"
NUM1 -ne NUM2
test
True if numbers are not equal
test "$PORT" -ne 8080 && echo "Using custom port"
NUM1 -lt NUM2
test
True if NUM1 is less than NUM2
[ "$AGE" -lt 18 ] && echo "Minor"
NUM1 -le NUM2
test
True if NUM1 is less than or equal to NUM2
test "$SCORE" -le 100 && echo "Valid score"
NUM1 -gt NUM2
test
True if NUM1 is greater than NUM2
[ "$TEMP" -gt 30 ] && echo "Hot!"
NUM1 -ge NUM2
test
True if NUM1 is greater than or equal to NUM2
test "$VERSION" -ge 2 && echo "Version 2 or higher"

Examples

File Tests

if test -f config.json; then
  echo "Config file found"
else
  echo "Config file missing"
fi

String Tests

if [ -z "$INPUT" ]; then
  echo "No input provided"
fi

Numeric Comparisons

COUNT=5
if test "$COUNT" -gt 0; then
  echo "Count is positive"
fi

Practical Use Cases

File Validation

# Check if required files exist
test -f package.json || echo "Error: package.json not found"
test -d node_modules || echo "Error: dependencies not installed"

Configuration Validation

# Validate environment variables
if [ -z "$DB_HOST" ]; then
  echo "Error: DB_HOST not set"
  exit 1
fi

if [ -z "$DB_PORT" ]; then
  echo "Using default port"
  export DB_PORT=5432
fi

Conditional Execution

# Run different commands based on environment
if [ "$ENV" = "production" ]; then
  echo "Running production build"
else
  echo "Running development build"
fi

Script Safety Checks

# Check prerequisites before running
test -f .env || echo "Warning: .env file missing"
test -d logs || mkdir logs
test -n "$USER" || export USER=default

Version Checking

# Check version compatibility
VERSION=2
if [ "$VERSION" -ge 2 ]; then
  echo "Using new API"
else
  echo "Using legacy API"
fi

Input Validation

# Validate user input
read INPUT

if [ -z "$INPUT" ]; then
  echo "Error: Input cannot be empty"
  exit 1
fi

if [ "$INPUT" = "quit" ]; then
  echo "Exiting..."
  exit 0
fi

Combining Tests

Use shell operators to combine multiple tests:
# AND: Both conditions must be true
test -f config.json && test -n "$API_KEY" && echo "Ready"

# OR: Either condition must be true
test -f config.yaml || test -f config.json || echo "No config found"

# Complex conditions
if [ -f data.txt ] && [ -n "$PROCESS" ]; then
  echo "Processing data.txt"
fi

Common Patterns

Set Default Value

test -z "$PORT" && export PORT=8080
echo "Using port: $PORT"

Create Directory if Missing

test -d output || mkdir output

Check Multiple Files

if [ -f index.html ] && [ -f style.css ] && [ -f script.js ]; then
  echo "All files present"
else
  echo "Missing files"
fi

Validate Number Range

VALUE=50
if [ "$VALUE" -ge 0 ] && [ "$VALUE" -le 100 ]; then
  echo "Valid percentage"
fi

String Pattern Matching

FILENAME="document.txt"
test "$FILENAME" = "document.txt" && echo "Found document"

Exit Status

When the condition is true:
test -f existing-file.txt
echo $?
# Output: 0

Notes

  • Always quote variables to handle empty values correctly: [ -z "$VAR" ]
  • Use -eq, -ne, etc. for numeric comparisons, not = or !=
  • Use = or != for string comparisons, not -eq or -ne
  • Spaces are required around brackets: [ -f file ], not [-f file]
  • The closing ] is required when using [ syntax
Common mistakes:
# Wrong: no spaces around brackets
[-f file.txt]

# Wrong: missing closing bracket
[ -f file.txt

# Wrong: using -eq for strings
test "$STR" -eq "value"  # Use = instead

# Wrong: using = for numbers
test "$NUM" = 10  # Use -eq instead

# Wrong: unquoted variable
test -z $VAR  # Should be "$VAR"
  • true - Always returns success (exit code 0)
  • false - Always returns failure (exit code 1)
  • which - Check if command exists
  • stat - Display detailed file information

Build docs developers (and LLMs) love