Skip to content

Conditionals

Control flow statements allow you to make decisions in your scripts based on conditions. This chapter covers if/elif/else statements, the test command, and best practices for writing conditional logic in bash scripts used for DevOps and system administration.


if_basic.sh
#!/usr/bin/env bash
# Simple if statement
if [ condition ]; then
# commands to execute if condition is true
echo "Condition is true"
fi
if_else.sh
#!/usr/bin/env bash
age=18
if [ "$age" -ge 18 ]; then
echo "You are an adult"
else
echo "You are a minor"
fi
if_elif_else.sh
#!/usr/bin/env bash
score=85
if [ "$score" -ge 90 ]; then
echo "Grade: A"
elif [ "$score" -ge 80 ]; then
echo "Grade: B"
elif [ "$score" -ge 70 ]; then
echo "Grade: C"
elif [ "$score" -ge 60 ]; then
echo "Grade: D"
else
echo "Grade: F"
fi

The [ command (also known as test) evaluates conditions.

test_basic.sh
#!/usr/bin/env bash
# Numeric comparisons
x=10
y=20
[ "$x" -eq 10 ] && echo "x equals 10"
[ "$x" -ne "$y" ] && echo "x is not equal to y"
[ "$x" -lt "$y" ] && echo "x is less than y"
[ "$x" -le 10 ] && echo "x is less than or equal to 10"
[ "$y" -gt "$x" ] && echo "y is greater than x"
[ "$y" -ge 20 ] && echo "y is greater than or equal to 20"

[[ ]] is an enhanced version of [ ] that supports additional features.

test_modern.sh
#!/usr/bin/env bash
# Pattern matching with [[ ]]
file="report.pdf"
# Check if file ends with .pdf
if [[ "$file" == *.pdf ]]; then
echo "This is a PDF file"
fi
# Regex matching (bash 3+)
email="user@example.com"
if [[ "$email" =~ ^[a-z]+@[a-z]+\.[a-z]+$ ]]; then
echo "Valid email format"
fi
# No word splitting
text="hello world"
if [[ $text == "hello world" ]]; then
echo "Text matches"
fi

numeric_comparison.sh
#!/usr/bin/env bash
# Check system resources for monitoring
# CPU load threshold
CPU_LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',')
CPU_LOAD_INT=${CPU_LOAD%.*}
if [ "$CPU_LOAD_INT" -gt 4 ]; then
echo "WARNING: High CPU load: $CPU_LOAD"
fi
# Memory usage percentage
MEM_TOTAL=$(free | grep Mem | awk '{print $2}')
MEM_USED=$(free | grep Mem | awk '{print $3}')
MEM_PERCENT=$((MEM_USED * 100 / MEM_TOTAL))
if [ "$MEM_PERCENT" -gt 80 ]; then
echo "WARNING: High memory usage: ${MEM_PERCENT}%"
fi
string_comparison.sh
#!/usr/bin/env bash
# Check if string is empty
name=""
if [ -z "$name" ]; then
echo "Name is empty"
fi
# Check if string is not empty
text="Hello"
if [ -n "$text" ]; then
echo "Text is not empty"
fi
# String equality
status="running"
if [ "$status" = "running" ]; then
echo "Service is running"
fi
# String not equal
env="production"
if [ "$env" != "development" ]; then
echo "Not in development environment"
fi

file_tests.sh
#!/usr/bin/env bash
file="/etc/passwd"
directory="/tmp"
# File exists
if [ -e "$file" ]; then
echo "File exists"
fi
# Regular file
if [ -f "$file" ]; then
echo "Regular file"
fi
# Directory
if [ -d "$directory" ]; then
echo "Directory exists"
fi
# Readable
if [ -r "$file" ]; then
echo "File is readable"
fi
# Writable
if [ -w "$file" ]; then
echo "File is writable"
fi
# Executable
if [ -x "/bin/bash" ]; then
echo "Bash is executable"
fi
# Non-empty file
if [ -s "$file" ]; then
echo "File is not empty"
fi
file_compare.sh
#!/usr/bin/env bash
file1="/tmp/file1.txt"
file2="/tmp/file2.txt"
# Create test files for demonstration
touch "$file1" "$file2"
sleep 1
touch "$file2" # Make file2 newer
# file1 is newer than file2
if [ "$file1" -nt "$file2" ]; then
echo "$file1 is newer"
fi
# file1 is older than file2
if [ "$file1" -ot "$file2" ]; then
echo "$file1 is older"
fi

and_condition.sh
#!/usr/bin/env bash
# Multiple conditions must all be true
age=25
has_license=true
if [ "$age" -ge 18 ] && [ "$has_license" = true ]; then
echo "You can drive"
fi
# Alternative with -a (deprecated but still works)
if [ "$age" -ge 18 -a "$has_license" = true ]; then
echo "You can drive"
fi
# With [[ ]] (preferred)
if [[ "$age" -ge 18 && "$has_license" = true ]]; then
echo "You can drive"
fi
or_condition.sh
#!/usr/bin/env bash
# At least one condition must be true
day="Saturday"
if [ "$day" = "Saturday" ] || [ "$day" = "Sunday" ]; then
echo "It's the weekend!"
fi
# Alternative with -o (deprecated)
if [ "$day" = "Saturday" -o "$day" = "Sunday" ]; then
echo "It's the weekend!"
fi
# With [[ ]] (preferred)
if [[ "$day" == "Saturday" || "$day" == "Sunday" ]]; then
echo "It's the weekend!"
fi
not_condition.sh
#!/usr/bin/env bash
file="/tmp/test.txt"
# Check if file does NOT exist
if [ ! -f "$file" ]; then
echo "File does not exist"
fi
# Check if NOT equal
value=10
if [ ! "$value" -eq 5 ]; then
echo "Value is not 5"
fi

nested_conditionals.sh
#!/usr/bin/env bash
# Nested if statements for complex logic
service="nginx"
if systemctl is-active --quiet "$service"; then
echo "$service is running"
if systemctl is-enabled --quiet "$service"; then
echo "$service is enabled at boot"
else
echo "$service is NOT enabled at boot"
fi
else
echo "$service is NOT running"
# Ask if user wants to start it
read -p "Start $service? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
sudo systemctl start "$service"
echo "$service started"
fi
fi

case_modification.sh
#!/usr/bin/env bash
# Convert to lowercase for comparison
input="Y"
if [[ "${input,,}" = "y" ]]; then
echo "Yes"
fi
# Convert to uppercase for comparison
input="production"
if [[ "${input^^}" = "PRODUCTION" ]]; then
echo "Production environment"
fi

service_health.sh
#!/usr/bin/env bash
set -euo pipefail
# Check multiple services
check_service() {
local service="$1"
if systemctl is-active --quiet "$service"; then
echo "$service is running"
return 0
else
echo "$service is NOT running"
return 1
fi
}
echo "=== Service Health Check ==="
services=("nginx" "postgresql" "redis")
all_healthy=true
for service in "${services[@]}"; do
if ! check_service "$service"; then
all_healthy=false
fi
done
if [ "$all_healthy" = true ]; then
echo "All services are healthy"
exit 0
else
echo "Some services are down!"
exit 1
fi
validate_env.sh
#!/usr/bin/env bash
# Validate required environment variables
required_vars=("DB_HOST" "DB_PORT" "DB_NAME" "DB_USER" "DB_PASSWORD")
missing=()
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
missing+=("$var")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
echo "ERROR: Missing required environment variables:"
for var in "${missing[@]}"; do
echo " - $var"
done
exit 1
fi
echo "All required environment variables are set"
deploy_validation.sh
#!/usr/bin/env bash
set -euo pipefail
# Validate deployment prerequisites
validate_deployment() {
local env="$1"
local version="$2"
# Validate environment
if [[ ! "$env" =~ ^(staging|production)$ ]]; then
echo "ERROR: Invalid environment: $env"
return 1
fi
# Validate version format (semantic versioning)
if [[ ! "$version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "ERROR: Invalid version format: $version"
echo "Expected format: v1.2.3"
return 1
fi
# Check disk space (at least 1GB free)
local disk_free=$(df -BG / | tail -1 | awk '{print $4}' | tr -d 'G')
if [ "$disk_free" -lt 1 ]; then
echo "ERROR: Less than 1GB disk space available"
return 1
fi
# Check if previous deployment is complete
if [ -f /var/run/deployment.pid ]; then
echo "ERROR: Another deployment is in progress"
return 1
fi
echo "Validation passed for $env $version"
return 0
}
# Run validation
if validate_deployment "production" "v1.2.3"; then
echo "Starting deployment..."
else
echo "Deployment validation failed"
exit 1
fi
backup_decision.sh
#!/usr/bin/env bash
set -euo pipefail
# Determine if backup is needed
BACKUP_DIR="/backups"
SOURCE_DIR="/data"
# Check if source directory exists
if [ ! -d "$SOURCE_DIR" ]; then
echo "ERROR: Source directory does not exist"
exit 1
fi
# Check if backup directory exists
if [ ! -d "$BACKUP_DIR" ]; then
echo "Creating backup directory..."
mkdir -p "$BACKUP_DIR"
fi
# Get last backup time
LAST_BACKUP_FILE="$BACKUP_DIR/.last_backup"
if [ -f "$LAST_BACKUP_FILE" ]; then
LAST_BACKUP=$(cat "$LAST_BACKUP_FILE")
HOURS_SINCE=$(( $(date +%s) - LAST_BACKUP ))
HOURS_SINCE=$(( HOURS_SINCE / 3600 ))
echo "Last backup: $HOURS_SINCE hours ago"
if [ "$HOURS_SINCE" -lt 24 ]; then
echo "Backup not needed (less than 24 hours)"
exit 0
fi
fi
# Perform backup
echo "Starting backup..."
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
tar -czf "$BACKUP_DIR/backup_${TIMESTAMP}.tar.gz" "$SOURCE_DIR"
# Update last backup time
date +%s > "$LAST_BACKUP_FILE"
echo "Backup completed: backup_${TIMESTAMP}.tar.gz"

Terminal window
# WRONG - can cause errors
if [ $var = "value" ]; then
echo "Matches"
fi
# CORRECT
if [ "$var" = "value" ]; then
echo "Matches"
fi
Terminal window
# [ ] - older, less features
# [[ ]] - modern, more features
# [[ ]] handles empty variables better
var=""
[ $var = "" ] # ERROR: Argument expected
[[ $var = "" ]] # Works fine
Terminal window
# WRONG - compares as strings
if [ 10 -gt 2 ]; then
echo "10 > 2"
fi
# CORRECT - uses numeric comparison
if (( 10 > 2 )); then
echo "10 > 2"
fi
Terminal window
# Complex - hard to read
if [ "$var" = "a" ] || [ "$var" = "b" ] || [ "$var" = "c" ]; then
echo "Valid"
fi
# Better - use pattern matching
if [[ "$var" =~ ^[abc]$ ]]; then
echo "Valid"
fi
# Even better - use case (for simple values)
case "$var" in
a|b|c) echo "Valid" ;;
esac

Terminal window
# Using if
if grep -q "pattern" file.txt; then
echo "Found"
fi
# Using && (short-circuit)
grep -q "pattern" file.txt && echo "Found"
Terminal window
# Using if
if ! grep -q "pattern" file.txt; then
echo "Not found"
fi
# Using || (short-circuit)
grep -q "pattern" file.txt || echo "Not found"
Terminal window
# Using && and ||
[ "$status" = "active" ] && echo "Running" || echo "Stopped"
# More complex
status=$([ "$val" -gt 0 ] && echo "positive" || echo "non-positive")

In this chapter, you learned about:

  • ✅ Basic if statements
  • ✅ If-else and if-elif-else statements
  • ✅ The test command ([ ])
  • ✅ The modern test command ([[ ]])
  • ✅ Numeric comparisons
  • ✅ String comparisons
  • ✅ File condition tests
  • ✅ Combining conditions with AND, OR, NOT
  • ✅ Nested conditionals
  • ✅ Case modification in conditionals
  • ✅ Practical DevOps examples
  • ✅ Best practices

  1. Write a script that checks if a number is positive, negative, or zero
  2. Create a script that checks if a file exists and is readable
  3. Write a script that validates a username
  1. Create a script that checks multiple service statuses
  2. Write a deployment validation script
  3. Implement environment variable validation
  1. Create a comprehensive health check script
  2. Write a backup decision script with multiple conditions
  3. Implement a complex validation system for deployment

Continue to the next chapter to learn about case statements.


Previous Chapter: Operators Next Chapter: Case Statements