Bash If...Else

Making decisions in your Bash scripts

🔀 What is If...Else?

If...Else statements let your script make decisions based on conditions. They check if something is true or false and execute different code accordingly, making your scripts smart and interactive.


#!/bin/bash
age=18
if [ $age -ge 18 ]; then
    echo "You are an adult"
fi
                                    

Output:

You are an adult

Conditional Statements

If Statement

Execute code when true

if [ condition ]; then
    # code
fi
↔️

If-Else

Choose between two paths

if [ condition ]; then
    # code
else
    # code
fi
🔀

Elif

Multiple conditions

if [ cond1 ]; then
    # code
elif [ cond2 ]; then
    # code
fi
🎯

Nested If

If inside if

if [ cond1 ]; then
    if [ cond2 ]; then
        # code
    fi
fi

🔹 Simple If Statement

The basic if statement executes code only when its condition evaluates to true. Syntax: if [ condition ]; then commands; fi. The condition is tested inside square brackets (or double brackets [[ ]] for more features). If true, the commands between then and fi run. This is the core of decision-making in scripts. For example, if [ -f "file.txt" ]; then echo "File exists"; fi. It's the simplest form of conditional logic, enabling scripts to react to different states and inputs dynamically.

#!/bin/bash

# Check if number is positive
number=10

if [ $number -gt 0 ]; then
    echo "$number is positive"
fi

# Check if file exists
filename="data.txt"

if [ -f "$filename" ]; then
    echo "File $filename exists"
fi

# Check string equality
username="admin"

if [ "$username" = "admin" ]; then
    echo "Welcome, administrator!"
fi

Output:

10 is positive
File data.txt exists
Welcome, administrator!

🔹 If-Else Statement

Extend if with else to provide an alternative execution path when the condition is false. Structure: if [ condition ]; then commands1; else commands2; fi. This ensures the script always takes some action. For instance, if [ -d "/backup" ]; then echo "Directory exists"; else mkdir /backup; fi. The else block handles the negation of the if condition cleanly. It's essential for robust scripts that must manage both expected and unexpected scenarios without halting.

#!/bin/bash

# Check even or odd
number=7

if [ $((number % 2)) -eq 0 ]; then
    echo "$number is even"
else
    echo "$number is odd"
fi

# Check age eligibility
age=16

if [ $age -ge 18 ]; then
    echo "You can vote"
else
    echo "You cannot vote yet"
fi

# Check password
password="secret123"

if [ "$password" = "admin123" ]; then
    echo "Access granted"
else
    echo "Access denied"
fi

Output:

7 is odd
You cannot vote yet
Access denied

🔹 If-Elif-Else Statement

Use elif (else if) to test multiple conditions sequentially until one matches. Syntax: if cond1; then ...; elif cond2; then ...; else ...; fi. The script checks each condition in order; the first true condition triggers its block, skipping the rest. This is cleaner and more efficient than nesting multiple if statements when dealing with several exclusive possibilities. For example, checking file type: is it a regular file, a directory, or a symlink? It organizes complex decision trees into a linear, readable flow.

#!/bin/bash

# Grade system
score=75

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

# Temperature check
temp=25

if [ $temp -gt 30 ]; then
    echo "It's hot"
elif [ $temp -gt 20 ]; then
    echo "It's warm"
elif [ $temp -gt 10 ]; then
    echo "It's cool"
else
    echo "It's cold"
fi

Output:

Grade: C
It's warm

🔹 Nested If Statements

Nested if statements place one conditional inside another, enabling multi-layered logic. Each level adds a dependent condition that's only evaluated if the outer condition is true. For example, before writing to a file, you might check if it exists (outer if) and then if it's writable (inner if). While powerful, deep nesting can reduce readability; consider using && operators or functions for simpler cases. This structure is necessary for intricate validation where decisions depend on a combination of factors assessed in a specific order.

#!/bin/bash

# Check login credentials
username="admin"
password="pass123"

if [ "$username" = "admin" ]; then
    echo "Username is correct"
    
    if [ "$password" = "pass123" ]; then
        echo "Password is correct"
        echo "Login successful!"
    else
        echo "Wrong password"
    fi
else
    echo "Username not found"
fi

# Age and license check
age=20
has_license="yes"

if [ $age -ge 18 ]; then
    if [ "$has_license" = "yes" ]; then
        echo "You can drive"
    else
        echo "You need a license"
    fi
else
    echo "You are too young to drive"
fi

Output:

Username is correct
Password is correct
Login successful!
You can drive

🔹 Using Logical Operators

Combine conditions within a single test using && (AND) and || (OR). Inside [[ ]], use && to require all conditions true, and || for at least one true. For example, if [[ -f "$file" && -r "$file" ]]; then checks if a file exists AND is readable. This consolidates logic, often avoiding the need for nested if statements. It makes conditions more declarative and easier to read. Parentheses can group sub-expressions for precise control over evaluation order within the test.

#!/bin/bash

# Check range with AND
number=15

if [ $number -gt 10 ] && [ $number -lt 20 ]; then
    echo "$number is between 10 and 20"
fi

# Check multiple conditions with OR
day="Saturday"

if [ "$day" = "Saturday" ] || [ "$day" = "Sunday" ]; then
    echo "It's the weekend!"
fi

# Complex condition
age=25
income=50000

if [ $age -ge 18 ] && [ $income -ge 30000 ]; then
    echo "Loan approved"
else
    echo "Loan denied"
fi

Output:

15 is between 10 and 20
It's the weekend!
Loan approved

🔹 Case Statement Alternative

The case statement matches a variable against multiple patterns, offering a cleaner syntax than long if-elif chains. Structure: case $var in pattern1) commands;; pattern2) commands;; *) default;; esac. Each pattern is checked; the first match executes its associated commands until ;;. The wildcard *) acts as the default catch-all. Ideal for menu choices, command dispatchers, or parsing user input. Example: handling different file extensions (*.txt|*.log). It's more readable and maintainable for multi-way branches.

#!/bin/bash

# Menu selection
choice="2"

case $choice in
    1)
        echo "You selected Option 1"
        ;;
    2)
        echo "You selected Option 2"
        ;;
    3)
        echo "You selected Option 3"
        ;;
    *)
        echo "Invalid choice"
        ;;
esac

# Day of week
day="Monday"

case $day in
    Monday|Tuesday|Wednesday|Thursday|Friday)
        echo "It's a weekday"
        ;;
    Saturday|Sunday)
        echo "It's the weekend"
        ;;
    *)
        echo "Invalid day"
        ;;
esac

Output:

You selected Option 2
It's a weekday

🧠 Test Your Knowledge

What keyword ends an if statement in Bash?