Guide Bash-Scripting Beginner

Conditions

if/elif/else, case statements, and combining conditions in Bash for real decision-making logic in scripts.

3 min read

Basic if / elif / else

ENVIRONMENT="staging"

if [ "$ENVIRONMENT" = "production" ]; then
    echo "Deploying to PRODUCTION — extra checks required"
elif [ "$ENVIRONMENT" = "staging" ]; then
    echo "Deploying to staging"
else
    echo "Unknown environment: $ENVIRONMENT"
    exit 1
fi

How Bash Evaluates “Truth”

Unlike most languages, Bash conditions don’t test true/false directly — they test a command’s exit status. 0 means success (true), anything non-zero means failure (false).

flowchart LR A["if COMMAND"] --> B{"Exit status?"} B -->|"0 (success)"| C[Run the 'then' block] B -->|"non-zero (failure)"| D[Run 'elif'/'else', or skip]
if grep -q "ERROR" app.log; then    # true if grep FINDS a match (exit 0)
    echo "Errors found"
fi

if [ -f "config.yaml" ]; then         # [ ] is itself just a command that returns exit status
    echo "Config exists"
fi

if ping -c1 -W1 8.8.8.8 &>/dev/null; then
    echo "Internet is reachable"
fi

One-Liners With && and ||

[ -f "app.log" ] && echo "log exists"
[ -f "app.log" ] || echo "log missing"

command1 && command2 && command3   # run each ONLY if the previous succeeded — a simple pipeline of dependent steps

case Statements

case is often cleaner than a long if/elif chain when matching one value against several patterns.

read -p "Environment (dev/staging/prod): " ENV

case "$ENV" in
    dev)
        echo "Deploying to development"
        ;;
    staging)
        echo "Deploying to staging"
        ;;
    prod|production)
        echo "Deploying to PRODUCTION"
        ;;
    *)
        echo "Unknown environment: $ENV"
        exit 1
        ;;
esac

case also supports glob patterns:

case "$1" in
    *.txt)
        echo "Text file" ;;
    *.tar.gz|*.tgz)
        echo "Compressed archive" ;;
    [0-9]*)
        echo "Starts with a digit" ;;
    *)
        echo "Unknown type" ;;
esac

Combining Multiple Conditions

if [ "$ENVIRONMENT" = "production" ] && [ "$FORCE_DEPLOY" != "true" ]; then
    echo "Production deploys require FORCE_DEPLOY=true"
    exit 1
fi

if [[ -f "$CONFIG" && -r "$CONFIG" ]]; then
    echo "Config exists and is readable"
fi

Nested Conditions

if [ -d "$APP_DIR" ]; then
    if [ -f "$APP_DIR/config.yaml" ]; then
        echo "Ready to deploy"
    else
        echo "Missing config.yaml" >&2
        exit 1
    fi
else
    echo "App directory not found: $APP_DIR" >&2
    exit 1
fi

Production Considerations

  • case is often preferable to a long if/elif chain for command-line argument dispatch — it’s more readable and self-documenting.
  • Redirect noisy command output to /dev/null (as with the ping example) when you only care about the exit status, not the output itself.
  • Deeply nested if blocks are a code smell — consider early returns/exit on invalid conditions instead of nesting the “happy path” deeper each time.

Quick Interview Answer

“Bash if doesn’t test true/false — it tests the exit status of a command (0 = success = true). That’s why if grep -q pattern file and if [ -f file ] both work: grep and [ are just commands returning an exit code. case statements are the cleaner choice when matching one variable against several fixed patterns, including glob patterns like *.txt.”

Common Mistakes

  • Forgetting Bash conditions are about EXIT STATUS, not boolean values, and being confused when a command “acts weird” in an if.
  • Missing the ;; terminator on a case branch.
  • Writing deeply nested if chains instead of using early exits to flatten the logic.

Add More Questions to This Guide

Know a question that should be here? Share it and help the community!

Open Google Form