How to Use Conditional Statements in Bash

How to Use Conditional Statements in Bash

How to Use Conditional Statements in Bash

Every useful script eventually needs to make a decision. Should it delete the file or not? Is the disk almost full? Did the user type “yes” or “no”? That’s where conditional statements come in. In this guide, I’ll break down how if, elif, else, and case work in Bash, with plenty of real examples you can copy straight into your own scripts.

What Are Conditional Statements?

A conditional statement lets a script choose between different paths based on whether something is true or false. In Bash, “true” and “false” aren’t quite like in other languages — they’re based on exit status codes. A command that exits with status 0 is considered successful (true), and anything else is considered a failure (false).

The if Statement

Basic Syntax

if [ condition ]
then
    command
fi

Example 1: Simple Number Comparison

#!/bin/bash

num=10

if [ $num -gt 5 ]
then
    echo "The number is greater than 5"
fi

Output:

The number is greater than 5

Example 2: Using if...else

#!/bin/bash

age=16

if [ $age -ge 18 ]
then
    echo "You are an adult"
else
    echo "You are a minor"
fi

Output:

You are a minor

Example 3: Using if...elif...else

#!/bin/bash

marks=75

if [ $marks -ge 90 ]
then
    echo "Grade: A"
elif [ $marks -ge 75 ]
then
    echo "Grade: B"
elif [ $marks -ge 60 ]
then
    echo "Grade: C"
else
    echo "Grade: F"
fi

Output:

Grade: B

Bash checks each condition top to bottom and runs the first block whose condition is true, skipping the rest.

Comparison Operators

For numbers:

OperatorMeaning
-eqequal to
-nenot equal to
-gtgreater than
-ltless than
-gegreater than or equal to
-leless than or equal to

For strings:

OperatorMeaning
=equal
!=not equal
-zstring is empty
-nstring is not empty

Example: String Comparison

#!/bin/bash

name="admin"

if [ "$name" = "admin" ]
then
    echo "Welcome, administrator"
else
    echo "Access denied"
fi

Output:

Welcome, administrator

File Test Operators

Bash has built-in checks for files and directories, which I use constantly in setup and deployment scripts:

OperatorMeaning
-efile exists
-fis a regular file
-dis a directory
-ris readable
-wis writable
-xis executable
-sfile exists and is not empty

Example: Checking If a File Exists

#!/bin/bash

file="/etc/passwd"

if [ -f "$file" ]
then
    echo "$file exists and is a regular file"
else
    echo "$file does not exist"
fi

Output:

/etc/passwd exists and is a regular file

Logical Operators: AND, OR, NOT

You can combine multiple conditions using && (AND), || (OR), and ! (NOT).

#!/bin/bash

age=25
citizen="yes"

if [ $age -ge 18 ] && [ "$citizen" = "yes" ]
then
    echo "Eligible to vote"
else
    echo "Not eligible to vote"
fi

Output:

Eligible to vote

Using [[ ]] Instead of [ ]

Bash provides an extended test command [[ ]], which is generally safer and more powerful than the POSIX [ ]. It supports pattern matching and doesn’t require quoting variables as strictly.

#!/bin/bash

filename="report.txt"

if [[ $filename == *.txt ]]
then
    echo "This is a text file"
fi

Output:

This is a text file

Notice how *.txt works as a pattern inside [[ ]] — that wouldn’t work reliably inside [ ].

The case Statement

When you have many possible values to check against a single variable, case is far cleaner than a long chain of elif statements.

Basic Syntax

case $variable in
    pattern1)
        command
        ;;
    pattern2)
        command
        ;;
    *)
        default command
        ;;
esac

Example: Menu-Style Script

#!/bin/bash

echo "Enter a fruit name:"
read fruit

case $fruit in
    apple)
        echo "Apples are red or green"
        ;;
    banana)
        echo "Bananas are yellow"
        ;;
    grape)
        echo "Grapes grow in bunches"
        ;;
    *)
        echo "Unknown fruit"
        ;;
esac

Sample run:

Enter a fruit name:
banana
Bananas are yellow

The * pattern acts as a catch-all default, similar to else.

Example: Handling Command-Line Arguments

#!/bin/bash

case $1 in
    start)
        echo "Starting the service..."
        ;;
    stop)
        echo "Stopping the service..."
        ;;
    restart)
        echo "Restarting the service..."
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        ;;
esac

This is exactly the pattern you’ll see in traditional init scripts (/etc/init.d/*).

How This Works Internally

Real-World Use Cases

usage=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
if [ "$usage" -gt 90 ]
then
    echo "Warning: Disk usage is above 90%!"
fi
read -p "Enter your age: " age
if ! [[ $age =~ ^[0-9]+$ ]]
then
    echo "Please enter a valid number"
fi
if [ "$ENVIRONMENT" = "production" ]
then
    echo "Deploying to production servers"
else
    echo "Deploying to staging servers"
fi

Best Practices

Security Considerations

Optimization Tips

Troubleshooting Common Issues

Frequently Asked Questions

Q: What’s the difference between [ ] and [[ ]]? A: [ ] is the POSIX-compliant test command; [[ ]] is a Bash-specific keyword with more features like pattern matching and safer variable handling.

Q: Can I use case for numeric ranges? A: Yes, using patterns like [0-9]) or combining with ?(...) extended globs, though for true numeric ranges an if with -lt/-gt is often clearer.

Q: How do I check multiple conditions at once? A: Combine them with && (AND) or || (OR) inside [[ ]], e.g. if [[ $a -gt 5 && $b -lt 10 ]].

Common Mistakes to Avoid

Summary

Conditional statements are how your Bash scripts make decisions. if/elif/else handles general logic based on exit statuses and comparisons, while case shines when you’re matching one variable against many possible patterns. Understanding that Bash conditions are really about exit codes — not “true/false” in the traditional programming sense — will save you a lot of confusion as your scripts grow more complex.

References

Exit mobile version