Bash Case Statement
A case statement compares one value against a list of patterns and runs the code of the first match. It replaces long chains of if and elif lines and keeps menu-style scripts tidy.
A Railway Signal Analogy
A railway signal shows red, yellow, or green. The driver reads the color and picks one action: stop, slow down, or go. A case statement reads a value and picks one block of code in the same way.
+-----------------+
| value: $color |
+--------+--------+
|
+--------------+--------------+
| | |
v v v
"red" "yellow" "green"
Stop Slow down Go
Basic Syntax
case value in
pattern1)
commands
;;
pattern2)
commands
;;
*)
default commands
;;
esacEach block ends with ;;. The word esac (case spelled backward) closes the whole statement. The * pattern catches every value that matched nothing before it.
Example: Traffic Signal
#!/bin/bash
read -p "Enter signal color: " color
case $color in
red)
echo "Stop the vehicle"
;;
yellow)
echo "Slow down"
;;
green)
echo "Go ahead"
;;
*)
echo "Unknown color"
;;
esacOutput (input: green):
Go aheadMatch Several Patterns in One Block
The pipe symbol | means "or". Use it to share one block between several values.
#!/bin/bash
read -p "Answer yes or no: " reply
case $reply in
y|Y|yes|YES)
echo "You agreed"
;;
n|N|no|NO)
echo "You declined"
;;
*)
echo "Please type yes or no"
;;
esacUse Wildcards in Patterns
Patterns support the same wildcards as file names. The star matches any text, the question mark matches one character, and square brackets match a set.
#!/bin/bash
file=$1
case $file in
*.txt)
echo "Text document"
;;
*.jpg|*.png)
echo "Image file"
;;
*.sh)
echo "Shell script"
;;
[0-9]*)
echo "Name starts with a digit"
;;
*)
echo "Unknown file type"
;;
esacRun ./type.sh photo.png and the screen shows Image file.
Build a Simple Menu
#!/bin/bash
echo "1) Show date"
echo "2) Show folder"
echo "3) Show user"
echo "4) Exit"
read -p "Choose an option: " choice
case $choice in
1) date ;;
2) pwd ;;
3) whoami ;;
4) echo "Goodbye" ;;
*) echo "Invalid choice" ;;
esacShort commands fit on one line with ;; at the end. Longer blocks work better with one command per line.
Handle Command Line Actions
Service scripts often accept words like start and stop:
#!/bin/bash
case $1 in
start)
echo "Starting service..."
;;
stop)
echo "Stopping service..."
;;
restart)
echo "Restarting service..."
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esacCase Versus If
| Situation | Better Choice |
|---|---|
| One value, many fixed options | case |
| Number comparisons such as greater than | if |
| Pattern checks on file names | case |
| Several different conditions combined | if |
Common Mistakes
- A missing
;;merges two blocks into a syntax error. - A
*)pattern placed first catches every value and blocks the others. - Spaces inside patterns need quotation marks, such as
"New York"). - Case compares text only. Use
ifwith-gtor-ltfor number ranges.
Key Takeaways
casepicks one block from a list of patterns.- Each block ends with
;;, and the statement ends withesac. - Use
|to join several patterns and*)for the default block. - Wildcards make file type checks short and readable.
- Menus and service scripts use case statements often.
