Skip to main content

How to Use Case Statement in Bash

• 5 min read
bash case statement pattern matching conditionals

Quick Answer: What Is a Case Statement?

A case statement is Bash’s version of a switch statement—it checks one variable against multiple patterns and runs different code for each match. Use it instead of chained if-else statements: case $var in pattern1) commands;; pattern2) commands;; esac

Quick Comparison: Case vs If-Else

AspectCase StatementIf-Else
ReadabilityExcellent for many conditionsBetter for 2-3 conditions
PerformanceVery fastComparable
ComplexitySimpleCan get messy
Pattern matchingBuilt-in with wildcardsRequires extra work

Bottom line: Use case for multiple values of one variable; use if-else for different variables or complex logic.


What is a Case Statement?

A case statement is Bash’s way of handling multiple conditions elegantly. Think of it like a more readable alternative to chained if-else statements. Instead of writing dozens of if [ $var = "value1" ]; then ... elif [ $var = "value2" ]; then ..., you can use case to match against multiple patterns in one clean structure.

This is particularly useful when you’re checking a single variable against many possible values. It’s faster to read, easier to maintain, and less prone to typos.

Imagine you’re writing a script that takes a command as an argument: start, stop, or restart. With if-else, you’d write three separate conditions. With case, you write one clean block that’s easy to understand at a glance. This is where case statements shine—when one variable determines what should happen.

Basic Syntax

The basic structure is straightforward once you know what each part does. It’s case-sensitive, so the keyword is case (lowercase) at the start and esac (case backwards) at the end—a memorable mnemonic.

case $variable in
  pattern1)
    # Commands to run if $variable matches pattern1
    ;;
  pattern2)
    # Commands to run if $variable matches pattern2
    ;;
  *)
    # Default case if nothing matches
    ;;
esac

Here’s what’s happening: case starts the statement and $variable is what you’re checking. Each pattern ends with a closing parenthesis. The commands for that pattern follow. Critically, each pattern block must end with ;; (two semicolons)—this is required syntax and is a common source of errors. The *) is a wildcard pattern that matches anything—it’s your catch-all “default” case, similar to the else in if-else statements. The esac closes the entire case statement (it’s case spelled backwards, which is a nice memory aid).

When to Use Case Statements

Use case statements when:

  • You’re checking one variable against many values
  • You have more than 3 possible values to check
  • The conditions are distinct (not overlapping ranges)
  • You want cleaner, more readable code

Use if-else when:

  • You’re checking different variables
  • You have complex conditional logic (AND, OR combinations)
  • You only need 2-3 simple checks

Simple Example: Script Menus

Here’s a practical example where case statements shine—creating a simple script menu. This is one of the most common uses for case statements:

#!/bin/bash

echo "What would you like to do?"
echo "1) Show disk usage"
echo "2) List running processes"
echo "3) Check system uptime"
echo "4) Exit"
read -p "Enter your choice (1-4): " choice

case $choice in
  1)
    echo "=== Disk Usage ==="
    df -h
    ;;
  2)
    echo "=== Running Processes ==="
    ps aux | head -10
    ;;
  3)
    echo "=== System Uptime ==="
    uptime
    ;;
  4)
    echo "Goodbye!"
    exit 0
    ;;
  *)
    echo "Invalid choice. Please select 1-4."
    exit 1
    ;;
esac

When you run this script and select option 1, it displays disk usage. Select 3, and you get system uptime. Each case branch is labeled clearly and does one specific thing. It’s much cleaner and more readable than writing a chain of if [ "$choice" = "1" ]; then ... elif [ "$choice" = "2" ]; then ... statements.

Notice the *) pattern at the end—it catches any input that doesn’t match 1, 2, 3, or 4. This is good defensive programming. Without it, invalid input would silently do nothing, leaving users confused.

Pattern Matching with Wildcards

Case statements support wildcards, making them even more powerful. You can match against patterns, not just exact strings:

#!/bin/bash
read -p "Enter a filename: " filename

case $filename in
  *.txt)
    echo "This is a text file"
    ;;
  *.sh)
    echo "This is a shell script"
    ;;
  *.md)
    echo "This is a markdown file"
    ;;
  *)
    echo "Unknown file type"
    ;;
esac

If you enter “document.txt”, it matches the first pattern. “script.sh” matches the second. The *.txt pattern means “anything ending with .txt”.

Multiple Patterns for One Action

Sometimes you want multiple patterns to trigger the same action. Separate them with pipes:

#!/bin/bash
read -p "Enter your favorite color: " color

case $color in
  red|crimson|scarlet)
    echo "You like red!"
    ;;
  blue|azure|navy)
    echo "You like blue!"
    ;;
  green|lime|forest)
    echo "You like green!"
    ;;
  *)
    echo "I'm not sure about that color."
    ;;
esac

This lets you group similar values together without repeating code.

Real-World Example: Service Manager

Here’s a more substantial example - a script that starts, stops, or checks status of a service:

#!/bin/bash

SERVICE="nginx"

case "${1:-help}" in
  start)
    echo "Starting $SERVICE..."
    systemctl start "$SERVICE"
    echo "$SERVICE started successfully."
    ;;
  stop)
    echo "Stopping $SERVICE..."
    systemctl stop "$SERVICE"
    echo "$SERVICE stopped successfully."
    ;;
  status)
    echo "Checking $SERVICE status..."
    systemctl status "$SERVICE"
    ;;
  restart)
    echo "Restarting $SERVICE..."
    systemctl restart "$SERVICE"
    echo "$SERVICE restarted successfully."
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    echo ""
    echo "Examples:"
    echo "  $0 start      - Start the service"
    echo "  $0 stop       - Stop the service"
    echo "  $0 restart    - Restart the service"
    echo "  $0 status     - Check service status"
    exit 1
    ;;
esac

The "${1:-help}" syntax means “use the first argument, or use ‘help’ as default”. This script can be called as ./script.sh start or ./script.sh status.

Important Points to Remember

  • Each case branch must end with ;; (two semicolons)
  • The *) pattern acts as a default case (like else)
  • Patterns support wildcards: *, ?, [abc], [a-z]
  • Case statements are more efficient than chained if-else blocks
  • You don’t need parentheses around the variable - case $var in works fine
  • The esac keyword closes the entire case statement (case backwards)

Common Mistakes to Avoid

Forgetting the closing semicolons:

case $var in
  pattern1)
    echo "This"  # Missing ;;
  pattern2)
    echo "That"
    ;;
esac

This will cause a syntax error. Always include ;; at the end of each case.

Using multiple patterns without pipes:

# WRONG
case $color in
  red scarlet)  # This won't work
    echo "Red!"
    ;;
esac

# RIGHT
case $color in
  red|scarlet)  # Use pipes between patterns
    echo "Red!"
    ;;
esac

When to Use Case Statements

Use case statements when:

  • You’re checking one variable against many values
  • You have more than 3 conditions
  • The conditions are distinct and independent
  • You want cleaner, more readable code

Use if-else when:

  • You’re checking different variables
  • You have complex conditional logic
  • You only need 2-3 simple checks

Summary

Case statements are a powerful tool for handling multiple conditions in a clean, readable way. They’re perfect for building menus, parsing command-line arguments, and routing logic based on a single variable. Master case statements and your shell scripts will be easier to read and maintain.