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 inbegins the construct.WORDis 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.esaccloses the statement. It iscasespelled backwards.
| Component | Role | Example |
|---|---|---|
case WORD in | Starts the case statement and identifies the value to test. | case $CHOICE in |
pattern) | Begins a matching clause. | 1) |
commands | Runs when the pattern matches. | pwd |
;; | Ends the selected clause. | pwd ;; |
*) | Matches any input not matched earlier. | *) |
esac | Ends 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 input | Matched branch | Command or result |
|---|---|---|
1 | 1) | pwd prints the present working directory. |
2 | 2) | date prints the current date and time. |
3 | 3) | 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
CHOICErather than unclear names. - Keep menu labels synchronized with their corresponding case branches. If the prompt says option 3 lists files, the
3)branch should runls -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
readis the same variable used as the case word. For example, use bothread CHOICEandcase $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
caseprovides clear multi-branch control flow for discrete choices.- The tested value follows
case, patterns end with), clauses normally end with;;, andesaccloses the construct. - Bash selects the first matching pattern in written order.
*)is the usual catch-all branch and should normally be last.readcan collect menu input, which a case statement can dispatch to commands such aspwd,date, andls -l.
For related shell concepts, see Linux command-line topics, Bourne Again Shell Bash, and Show the Full Path Of Shell Commands.