Sagar.BlogArticle
All posts
All posts
Bash

The case Statement — Multi-Way Branching

The case statement is Bash's pattern-matching switch. Use it to write cleaner multi-branch logic than chains of if/elif — especially for string matching and option parsing.

January 12, 20266 min read
BashcaseControl FlowScripting

When you have many possible values for a variable and need to branch on each, a chain of elif statements becomes unwieldy. The case statement provides a cleaner pattern-matching alternative, similar to switch in C or JavaScript — but with glob patterns.

Basic case Syntax

case "$variable" in
    pattern1)
        # commands for pattern1
        ;;          # <-- two semicolons end each block
    pattern2)
        # commands for pattern2
        ;;
    pattern3 | pattern4)    # multiple patterns with |
        # commands for pattern3 OR pattern4
        ;;
    *)              # default — matches anything
        # fallback commands
        ;;
esac                # closes case (backwards: "esac")

Practical Examples

#!/usr/bin/env bash
# Day type checker

day=$(date +%A)    # full day name: Monday, Tuesday, ...

case "$day" in
    Monday | Tuesday | Wednesday | Thursday | Friday)
        echo "It's a weekday"
        ;;
    Saturday | Sunday)
        echo "It's the weekend!"
        ;;
    *)
        echo "Unknown day: $day"
        ;;
esac
#!/usr/bin/env bash
# Simple CLI menu

read -rp "Choose action [start|stop|restart|status]: " action

case "$action" in
    start)
        echo "Starting service..."
        ;;
    stop)
        echo "Stopping service..."
        ;;
    restart)
        echo "Restarting service..."
        ;;
    status)
        echo "Checking status..."
        ;;
    *)
        echo "Invalid action: $action" >&2
        echo "Valid: start, stop, restart, status" >&2
        exit 1
        ;;
esac

Pattern Matching in case

case uses glob patterns (the same as filename matching), not regex:

filename="report_2026.csv"

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

Fall-through with ;& and ;;&

By default, case stops after the first matching pattern (unlike C's switch). Bash 4 adds fall-through terminators:

case terminators

TerminatorBehaviour
;;Stop — don't check remaining patterns (default)
;&Fall-through — execute next pattern's block unconditionally
;;&Continue testing — check remaining patterns for more matches
level=3

case "$level" in
    3)
        echo "Level 3 specific setup"
        ;;&     # continue testing other patterns
    [2-3])
        echo "Common setup for level 2 and 3"
        ;;&
    [1-3])
        echo "Setup for levels 1, 2, and 3"
        ;;
esac
# Output for level=3:
# Level 3 specific setup
# Common setup for level 2 and 3
# Setup for levels 1, 2, and 3
Quick Check

What do the two semicolons `;;` at the end of a case pattern block do?

Exercise

Write a script file-action.sh that takes a filename as argument. Use case to:

  1. .sh files → print "Running shell script..." and execute it with bash
  2. .py files → print "Running Python script..." and execute with python3
  3. .txt or .md → print the file contents with cat
  4. Anything else → print "Don't know how to run: filename"