Linux online course

Linux Bash case Statement

Learn how to use the Bash case statement for clear multi-branch decisions, pattern matching, default handling, and interactive command menus.

A Bash case statement selects commands based on which pattern matches a word or variable value. It is useful when one value can have several expected outcomes, such as numbered menu choices.

For only two possible outcomes, an if statement may be sufficient. For several discrete choices, case is often clearer than a long chain of if, elif, and else tests. Other programming languages commonly provide a similar construct called a switch statement. More generally, this is a multiway branch: a decision with more than two possible branches.

Basic Bash case syntax

The general structure is:

case WORD in
    pattern)
        commands
        ;;
    another-pattern)
        other commands
        ;;
    *)
        default commands
        ;;
esac
  • case WORD in begins the construct. WORD is the value Bash tests, commonly a variable expansion such as $CHOICE.
  • pattern) starts a clause. The closing parenthesis separates the pattern from its commands.
  • Commands after the parenthesis run when that pattern matches.
  • ;; ends the clause. It conventionally stops evaluation after the selected branch.
  • *) is a wildcard catch-all pattern, normally used for the default branch.
  • esac closes the statement. It is case spelled backwards.
ComponentRoleExample
case WORD inStarts the case statement and identifies the value to test.case $CHOICE in
pattern)Begins a matching clause.1)
commandsRuns when the pattern matches.pwd
;;Ends the selected clause.pwd ;;
*)Matches any input not matched earlier.*)
esacEnds the case statement.esac

How Bash evaluates patterns

Bash compares the case word with patterns in the order they are written. When it finds the first matching pattern, it runs that clause's commands. The usual ;; terminator prevents evaluation from continuing to later clauses.

Patterns use shell pattern-matching rules. An exact pattern such as 1) matches the text 1. A pattern such as y|Y) matches either y or Y, and *) matches any text. Because input from read is text, numeric-looking choices such as 1 and 2 are matched as shell text patterns. Bash does not perform arithmetic comparison automatically in a case statement.

The default branch

The *) clause handles every input that did not match an earlier pattern. Use it to report invalid selections or unsupported input instead of silently doing nothing.

case $CHOICE in
    1) echo "First option" ;;
    2) echo "Second option" ;;
    *) echo "Invalid selection" ;;
esac

For example, 4, a word such as help, or an empty response reaches the default branch when only 1 and 2 are listed.

Interactive menu example

This script displays a menu, reads the user's response, and runs one command for each valid choice:

#!/bin/bash

echo "Choose an option:"
echo "1) Show the current directory"
echo "2) Show the current date and time"
echo "3) List directory contents"
echo "Enter 1, 2, or 3:"
read CHOICE

case $CHOICE in
    1)
        pwd
        ;;
    2)
        date
        ;;
    3)
        ls -l
        ;;
    *)
        echo "Invalid selection"
        ;;
esac
User inputMatched branchCommand or result
11)pwd prints the present working directory.
22)date prints the current date and time.
33)ls -l lists current-directory contents in long format.
Any unmatched input*)Prints an invalid-selection message.

Running the script

Save the code in a file such as menu.sh. The Bash shebang, #!/bin/bash, identifies the interpreter when the file is executed directly.

bash menu.sh

To execute it directly, make it executable first:

chmod +x menu.sh
./menu.sh

The commands in a matching branch execute in the script's current shell context. The working directory used by pwd and ls is the directory from which the script is run, unless the script changes directory with cd. For example, running /home/user/menu.sh while your terminal is in /tmp makes pwd and ls -l operate on /tmp.

Writing maintainable case statements

  • Use consistent indentation for patterns, command blocks, terminators, and esac.
  • Choose descriptive variable names such as CHOICE rather than unclear names.
  • Keep menu labels synchronized with their corresponding case branches. If the prompt says option 3 lists files, the 3) branch should run ls -l.
  • Always consider a default response for unexpected input.
  • Keep exact choices before broad patterns such as *).

Troubleshooting

A valid-looking input reaches the invalid branch

  • Check that the variable used by read is the same variable used as the case word. For example, use both read CHOICE and case $CHOICE in.
  • Verify that the pattern exactly corresponds to the entered value and menu label.
  • Look for unexpected whitespace or other characters in the input.
  • Test one input value at a time.

There is a syntax error near esac

  • Check that every pattern has its closing parenthesis, as in 1).
  • Confirm that each clause has a ;; terminator.
  • Make sure the statement ends with one final esac.

The wrong command runs

This often happens when a broad wildcard pattern appears before a specific choice. Move exact patterns above broad patterns and keep *) last.

The script does not execute as Bash

Run it explicitly with bash menu.sh, or add the Bash shebang and execute the file directly. A script intended for Bash may not behave correctly when interpreted by a different shell.

Summary

  • case provides clear multi-branch control flow for discrete choices.
  • The tested value follows case, patterns end with ), clauses normally end with ;;, and esac closes the construct.
  • Bash selects the first matching pattern in written order.
  • *) is the usual catch-all branch and should normally be last.
  • read can collect menu input, which a case statement can dispatch to commands such as pwd, date, and ls -l.

For related shell concepts, see Linux command-line topics, Bourne Again Shell Bash, and Show the Full Path Of Shell Commands.