Conditionals
Chapter 7: Control Flow - Conditionals
Section titled “Chapter 7: Control Flow - Conditionals”Overview
Section titled “Overview”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 Statements
Section titled “If Statements”Basic If Statement
Section titled “Basic If Statement”#!/usr/bin/env bash# Simple if statementif [ condition ]; then # commands to execute if condition is true echo "Condition is true"fiIf-Else Statement
Section titled “If-Else Statement”#!/usr/bin/env bashage=18
if [ "$age" -ge 18 ]; then echo "You are an adult"else echo "You are a minor"fiIf-Elif-Else Statement
Section titled “If-Elif-Else Statement”#!/usr/bin/env bashscore=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"fiTest Commands
Section titled “Test Commands”Using [ ] (test)
Section titled “Using [ ] (test)”The [ command (also known as test) evaluates conditions.
#!/usr/bin/env bash# Numeric comparisonsx=10y=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"Using [[ ]] (Modern Test)
Section titled “Using [[ ]] (Modern Test)”[[ ]] is an enhanced version of [ ] that supports additional features.
#!/usr/bin/env bash# Pattern matching with [[ ]]file="report.pdf"
# Check if file ends with .pdfif [[ "$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 splittingtext="hello world"if [[ $text == "hello world" ]]; then echo "Text matches"fiComparison Operators in Practice
Section titled “Comparison Operators in Practice”Numeric Comparisons
Section titled “Numeric Comparisons”#!/usr/bin/env bash# Check system resources for monitoring
# CPU load thresholdCPU_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 percentageMEM_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}%"fiString Comparisons
Section titled “String Comparisons”#!/usr/bin/env bash# Check if string is emptyname=""
if [ -z "$name" ]; then echo "Name is empty"fi
# Check if string is not emptytext="Hello"if [ -n "$text" ]; then echo "Text is not empty"fi
# String equalitystatus="running"
if [ "$status" = "running" ]; then echo "Service is running"fi
# String not equalenv="production"
if [ "$env" != "development" ]; then echo "Not in development environment"fiFile Condition Tests
Section titled “File Condition Tests”Common File Tests
Section titled “Common File Tests”#!/usr/bin/env bashfile="/etc/passwd"directory="/tmp"
# File existsif [ -e "$file" ]; then echo "File exists"fi
# Regular fileif [ -f "$file" ]; then echo "Regular file"fi
# Directoryif [ -d "$directory" ]; then echo "Directory exists"fi
# Readableif [ -r "$file" ]; then echo "File is readable"fi
# Writableif [ -w "$file" ]; then echo "File is writable"fi
# Executableif [ -x "/bin/bash" ]; then echo "Bash is executable"fi
# Non-empty fileif [ -s "$file" ]; then echo "File is not empty"fiFile Comparisons
Section titled “File Comparisons”#!/usr/bin/env bashfile1="/tmp/file1.txt"file2="/tmp/file2.txt"
# Create test files for demonstrationtouch "$file1" "$file2"sleep 1touch "$file2" # Make file2 newer
# file1 is newer than file2if [ "$file1" -nt "$file2" ]; then echo "$file1 is newer"fi
# file1 is older than file2if [ "$file1" -ot "$file2" ]; then echo "$file1 is older"fiCombining Conditions
Section titled “Combining Conditions”Using AND (&&)
Section titled “Using AND (&&)”#!/usr/bin/env bash# Multiple conditions must all be true
age=25has_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"fiUsing OR (||)
Section titled “Using OR (||)”#!/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!"fiUsing NOT (!)
Section titled “Using NOT (!)”#!/usr/bin/env bashfile="/tmp/test.txt"
# Check if file does NOT existif [ ! -f "$file" ]; then echo "File does not exist"fi
# Check if NOT equalvalue=10
if [ ! "$value" -eq 5 ]; then echo "Value is not 5"fiNested Conditionals
Section titled “Nested Conditionals”#!/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" fielse 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" fifiCase Modification in Conditionals
Section titled “Case Modification in Conditionals”#!/usr/bin/env bash# Convert to lowercase for comparisoninput="Y"
if [[ "${input,,}" = "y" ]]; then echo "Yes"fi
# Convert to uppercase for comparisoninput="production"
if [[ "${input^^}" = "PRODUCTION" ]]; then echo "Production environment"fiPractical Examples
Section titled “Practical Examples”Example 1: Service Health Check
Section titled “Example 1: Service Health Check”#!/usr/bin/env bashset -euo pipefail
# Check multiple servicescheck_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 fidone
if [ "$all_healthy" = true ]; then echo "All services are healthy" exit 0else echo "Some services are down!" exit 1fiExample 2: Environment Validation
Section titled “Example 2: Environment Validation”#!/usr/bin/env bash# Validate required environment variablesrequired_vars=("DB_HOST" "DB_PORT" "DB_NAME" "DB_USER" "DB_PASSWORD")
missing=()
for var in "${required_vars[@]}"; do if [ -z "${!var}" ]; then missing+=("$var") fidone
if [ ${#missing[@]} -gt 0 ]; then echo "ERROR: Missing required environment variables:" for var in "${missing[@]}"; do echo " - $var" done exit 1fi
echo "All required environment variables are set"Example 3: Deployment Validation
Section titled “Example 3: Deployment Validation”#!/usr/bin/env bashset -euo pipefail
# Validate deployment prerequisitesvalidate_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 validationif validate_deployment "production" "v1.2.3"; then echo "Starting deployment..."else echo "Deployment validation failed" exit 1fiExample 4: Backup Decision
Section titled “Example 4: Backup Decision”#!/usr/bin/env bashset -euo pipefail
# Determine if backup is neededBACKUP_DIR="/backups"SOURCE_DIR="/data"
# Check if source directory existsif [ ! -d "$SOURCE_DIR" ]; then echo "ERROR: Source directory does not exist" exit 1fi
# Check if backup directory existsif [ ! -d "$BACKUP_DIR" ]; then echo "Creating backup directory..." mkdir -p "$BACKUP_DIR"fi
# Get last backup timeLAST_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 fifi
# Perform backupecho "Starting backup..."TIMESTAMP=$(date +%Y%m%d_%H%M%S)tar -czf "$BACKUP_DIR/backup_${TIMESTAMP}.tar.gz" "$SOURCE_DIR"
# Update last backup timedate +%s > "$LAST_BACKUP_FILE"
echo "Backup completed: backup_${TIMESTAMP}.tar.gz"Best Practices
Section titled “Best Practices”Always Quote Variables
Section titled “Always Quote Variables”# WRONG - can cause errorsif [ $var = "value" ]; then echo "Matches"fi
# CORRECTif [ "$var" = "value" ]; then echo "Matches"fiUse [[ ]] Over [ ]
Section titled “Use [[ ]] Over [ ]”# [ ] - older, less features# [[ ]] - modern, more features
# [[ ]] handles empty variables bettervar=""[ $var = "" ] # ERROR: Argument expected[[ $var = "" ]] # Works fineUse Arithmetic Context for Numbers
Section titled “Use Arithmetic Context for Numbers”# WRONG - compares as stringsif [ 10 -gt 2 ]; then echo "10 > 2"fi
# CORRECT - uses numeric comparisonif (( 10 > 2 )); then echo "10 > 2"fiSimplify Complex Conditions
Section titled “Simplify Complex Conditions”# Complex - hard to readif [ "$var" = "a" ] || [ "$var" = "b" ] || [ "$var" = "c" ]; then echo "Valid"fi
# Better - use pattern matchingif [[ "$var" =~ ^[abc]$ ]]; then echo "Valid"fi
# Even better - use case (for simple values)case "$var" in a|b|c) echo "Valid" ;;esacCommon Patterns
Section titled “Common Patterns”Check Command Success
Section titled “Check Command Success”# Using ifif grep -q "pattern" file.txt; then echo "Found"fi
# Using && (short-circuit)grep -q "pattern" file.txt && echo "Found"Check Command Failure
Section titled “Check Command Failure”# Using ifif ! grep -q "pattern" file.txt; then echo "Not found"fi
# Using || (short-circuit)grep -q "pattern" file.txt || echo "Not found"Ternary-Like Pattern
Section titled “Ternary-Like Pattern”# Using && and ||[ "$status" = "active" ] && echo "Running" || echo "Stopped"
# More complexstatus=$([ "$val" -gt 0 ] && echo "positive" || echo "non-positive")Summary
Section titled “Summary”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
Exercises
Section titled “Exercises”Level 1: Basics
Section titled “Level 1: Basics”- Write a script that checks if a number is positive, negative, or zero
- Create a script that checks if a file exists and is readable
- Write a script that validates a username
Level 2: Intermediate
Section titled “Level 2: Intermediate”- Create a script that checks multiple service statuses
- Write a deployment validation script
- Implement environment variable validation
Level 3: Advanced
Section titled “Level 3: Advanced”- Create a comprehensive health check script
- Write a backup decision script with multiple conditions
- Implement a complex validation system for deployment
Next Steps
Section titled “Next Steps”Continue to the next chapter to learn about case statements.
Previous Chapter: Operators Next Chapter: Case Statements