Sagar.BlogArticle
All posts
All posts
Bash

Conditionals — if, elif, and else

Make decisions in your Bash scripts with if/elif/else. Understand the structure, common patterns, and how exit codes drive branching.

January 10, 20267 min read
BashConditionalsControl Flow

Decision-making is the backbone of automation. Without if, your script does the same thing regardless of conditions — no checking if a file exists, no different handling for success vs failure, no adapting to input. Once you understand how Bash if works under the hood, it makes complete sense.

How if Works — It's All Exit Codes

Bash's if statement doesn't check a boolean — it runs a command and checks whether it exits with code 0 (success = true) or non-zero (failure = false). Every command, including [, [[, and test, is evaluated this way.

# Basic structure
if command; then
    # runs if command exits 0
elif other_command; then
    # runs if other_command exits 0 (and first failed)
else
    # runs if all above failed
fi                  # ← closes the if block (literally "if" backwards)

# One-liner (semicolons allowed)
if [ -f file.txt ]; then echo "exists"; fi

fi closes if

Bash block closers are literally the keyword reversed: if...fi, case...esac. Don't forget fi! Forgetting it causes a confusing 'unexpected end of file' error.

Common if Patterns

# Check command success
if ping -c 1 google.com &>/dev/null; then
    echo "Network is up"
else
    echo "No network"
fi

# Check a string value
color="blue"
if [[ "$color" == "red" ]]; then
    echo "It's red"
elif [[ "$color" == "blue" ]]; then
    echo "It's blue"
else
    echo "Unknown color"
fi

# Check a number
age=25
if [[ "$age" -ge 18 ]]; then
    echo "Adult"
fi

Logical Operators — and, or, not

# AND — both conditions must be true
if [[ -f file.txt && -r file.txt ]]; then
    echo "file exists and is readable"
fi

# OR — at least one must be true
if [[ "$input" == "yes" || "$input" == "y" ]]; then
    echo "User said yes"
fi

# NOT — negate condition
if ! command -v docker &>/dev/null; then
    echo "Docker is not installed"
fi

# Chaining with && and || (without if)
mkdir /tmp/mydir && echo "Created OK" || echo "Failed to create"

Nested if Statements

#!/usr/bin/env bash

file="${1:-}"

if [[ -z "$file" ]]; then
    echo "No file provided" >&2
    exit 1
fi

if [[ -f "$file" ]]; then
    if [[ -r "$file" ]]; then
        echo "Reading $file..."
        cat "$file"
    else
        echo "File exists but is not readable" >&2
        exit 1
    fi
elif [[ -d "$file" ]]; then
    echo "$file is a directory, not a file"
else
    echo "$file does not exist"
fi

Inline Conditionals

# Short-circuit evaluation
[[ -f backup.tar.gz ]] && echo "Backup exists"
[[ -d /tmp/work ]]    || mkdir -p /tmp/work   # create if not exists

# These are equivalent to if/else but more concise
# Use sparingly — readability suffers in complex cases
Quick Check

What does Bash actually check when evaluating `if some_command; then`?

Exercise

Write a script check-user.sh that accepts a username as argument and:

  1. If no argument given → print "Usage..." and exit 1
  2. If the user exists on the system (use id username) → print "User alice exists"
  3. If the user doesn't exist → print "User alice not found"