case Statement
Multi-way conditional construct for pattern matching and selective execution in bash scripting.
Syntax
case EXPRESSION in
PATTERN1)
COMMANDS
;;
PATTERN2|PATTERN3)
COMMANDS
;;
*)
DEFAULT_COMMANDS
;;
esac
The case statement compares an expression against patterns and executes matching code blocks.
Basic Usage
Simple case statement
#!/bin/bash
read -p "Enter a day (1-7): " day
case $day in
1)
echo "Monday"
;;
2)
echo "Tuesday"
;;
3)
echo "Wednesday"
;;
4)
echo "Thursday"
;;
5)
echo "Friday"
;;
6)
echo "Saturday"
;;
7)
echo "Sunday"
;;
*)
echo "Invalid day"
;;
esac
Basic case statement with numeric patterns
String matching
#!/bin/bash
read -p "Enter your choice (yes/no): " choice
case $choice in
yes|y|YES|Y)
echo "You chose yes"
;;
no|n|NO|N)
echo "You chose no"
;;
*)
echo "Please enter yes or no"
;;
esac
String pattern matching with multiple options
Command line argument processing
#!/bin/bash
case $1 in
start)
echo "Starting service..."
;;
stop)
echo "Stopping service..."
;;
restart)
echo "Restarting service..."
;;
status)
echo "Checking service status..."
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
Process command line arguments
Pattern Matching
Wildcard patterns
#!/bin/bash
filename="$1"
case $filename in
*.txt)
echo "Text file"
;;
*.jpg|*.jpeg|*.png|*.gif)
echo "Image file"
;;
*.mp3|*.wav|*.flac)
echo "Audio file"
;;
*.mp4|*.avi|*.mkv)
echo "Video file"
;;
*.tar.gz|*.tgz)
echo "Compressed archive"
;;
*)
echo "Unknown file type"
;;
esac
Use wildcards for pattern matching
Character classes and ranges
#!/bin/bash
read -p "Enter a character: " char
case $char in
[a-z])
echo "Lowercase letter"
;;
[A-Z])
echo "Uppercase letter"
;;
[0-9])
echo "Digit"
;;
[!a-zA-Z0-9])
echo "Special character"
;;
*)
echo "Multiple characters or empty"
;;
esac
Character classes and ranges in patterns
Complex patterns
#!/bin/bash
input="$1"
case $input in
[Yy][Ee][Ss])
echo "Affirmative response"
;;
[Nn][Oo])
echo "Negative response"
;;
[0-9][0-9][0-9])
echo "Three-digit number"
;;
+([0-9]))
echo "Positive integer"
;;
-([0-9]))
echo "Negative integer"
;;
*@(gmail|yahoo|hotmail).com)
echo "Common email provider"
;;
*)
echo "No pattern matched"
;;
esac
Complex pattern matching examples
Advanced Usage
Multiple commands per case
#!/bin/bash
operation="$1"
file="$2"
case $operation in
backup)
echo "Creating backup of $file"
cp "$file" "$file.bak"
echo "Backup created: $file.bak"
ls -l "$file.bak"
;;
restore)
if [ -f "$file.bak" ]; then
echo "Restoring $file from backup"
cp "$file.bak" "$file"
echo "File restored"
else
echo "No backup found for $file"
exit 1
fi
;;
clean)
echo "Removing backup files"
rm -f *.bak
echo "Cleanup complete"
;;
*)
echo "Usage: $0 {backup|restore|clean} [filename]"
;;
esac
Multiple commands and nested conditions
Case with functions
#!/bin/bash
start_service() {
echo "Starting service..."
# Service start logic here
return 0
}
stop_service() {
echo "Stopping service..."
# Service stop logic here
return 0
}
show_status() {
echo "Service status: Running"
# Status check logic here
}
case $1 in
start)
start_service
;;
stop)
stop_service
;;
restart)
stop_service
sleep 2
start_service
;;
status)
show_status
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
Combine case statements with functions
Practical Examples
Menu system
#!/bin/bash
show_menu() {
echo "=== System Menu ==="
echo "1. Show disk usage"
echo "2. Show memory usage"
echo "3. Show running processes"
echo "4. Show network connections"
echo "5. Exit"
echo "=================="
}
while true; do
show_menu
read -p "Enter your choice (1-5): " choice
case $choice in
1)
echo "Disk Usage:"
df -h
;;
2)
echo "Memory Usage:"
free -h
;;
3)
echo "Running Processes:"
ps aux | head -10
;;
4)
echo "Network Connections:"
netstat -tuln | head -10
;;
5)
echo "Goodbye!"
exit 0
;;
*)
echo "Invalid choice. Please try again."
;;
esac
echo
read -p "Press Enter to continue..."
clear
done
Interactive menu system
File processing script
#!/bin/bash
process_file() {
local file="$1"
case $file in
*.log)
echo "Processing log file: $file"
tail -n 20 "$file"
;;
*.conf|*.config)
echo "Configuration file: $file"
grep -v '^#' "$file" | grep -v '^$'
;;
*.sh)
echo "Shell script: $file"
if [ -x "$file" ]; then
echo "Executable script"
else
echo "Non-executable script"
fi
;;
*.txt|*.md)
echo "Text document: $file"
wc -l "$file"
;;
*)
echo "Unknown file type: $file"
file "$file"
;;
esac
}
# Process all files in current directory
for file in *; do
if [ -f "$file" ]; then
process_file "$file"
echo "---"
fi
done
File processing based on extensions
System information script
#!/bin/bash
get_os_info() {
case $(uname -s) in
Linux)
echo "Operating System: Linux"
if [ -f /etc/os-release ]; then
. /etc/os-release
echo "Distribution: $NAME $VERSION"
fi
;;
Darwin)
echo "Operating System: macOS"
echo "Version: $(sw_vers -productVersion)"
;;
FreeBSD)
echo "Operating System: FreeBSD"
echo "Version: $(uname -r)"
;;
*)
echo "Operating System: $(uname -s)"
echo "Version: $(uname -r)"
;;
esac
}
get_arch_info() {
case $(uname -m) in
x86_64)
echo "Architecture: 64-bit x86"
;;
i386|i686)
echo "Architecture: 32-bit x86"
;;
arm64|aarch64)
echo "Architecture: 64-bit ARM"
;;
armv7l)
echo "Architecture: 32-bit ARM"
;;
*)
echo "Architecture: $(uname -m)"
;;
esac
}
get_os_info
get_arch_info
System information detection
Best Practices
case Statement Best Practices
- Always include a default case (*) for unmatched patterns
- Use double semicolons (;;) to terminate each case
- Group related patterns with | (pipe) separator
- Quote variables to prevent word splitting
- Use meaningful pattern names and comments
- Consider case sensitivity in pattern matching
- Test all possible input scenarios
Common Pitfalls
- Missing ;; - Each case must end with double semicolon
- Pattern order - More specific patterns should come first
- Quoting - Unquoted variables can cause issues
- Case sensitivity - Patterns are case-sensitive by default
- Globbing - Patterns use shell globbing, not regex