Bash case statement in shell scripts

In this Bash Tutorial, we shall learn the syntax and usage of the Bash case statement with example Bash scripts.

The Bash case statement is used when one expression can match one of many possible patterns. It is similar to a switch statement in other programming languages, but Bash uses shell patterns such as exact words, wildcard patterns, and alternative patterns separated with |.

Use case when a script has to respond to menu choices, command-line options, file extensions, operating system names, or status values. It often reads better than a long chain of if, elif, and else blocks.

Syntax of Bash case statement with esac and double semicolon

Syntax of Case statement in Bash Shell Scripting is as shown below :

</>
Copy
case EXPRESSION in
CASE1)
	COMMAND-LIST
	;;
CASE2)
	COMMAND-LIST
	;;


CASEN)
	COMMAND-LIST
	;;
esac

where

EXPRESSIONwhere expression evaluates to a value.
CASENOne of the value the expression could evaluate to.
COMMAND-LISTSet of commands to be run when a CASE matches.

In Bash, case starts the statement and esac ends it. Each pattern is followed by ). The command list for a matched pattern usually ends with ;;, which tells Bash to stop that case branch and continue after esac.

Note : Providing *  for a case can make the case to match to any value. This can be used as a default case when used as a last case.

For scripts that receive user input, it is a good practice to quote the expression as case "$choice" in. Quoting helps the script handle empty strings and values that contain spaces without accidental word splitting.

Example 1: Bash case statement with exact numeric patterns

In this example, we shall look into a simple scenario to illustrate case statement.

</>
Copy
#!/bin/bash

time=12

# if condition is true
case $time in
9)
	echo Good Morning!
	;;
12)
	echo Good Noon!
	;;
17)
	echo Good Evening!
	;;
21)
	echo Good Night!
	;;
esac
~$ ./bash-case-example 
Good Noon!

In the above example, the expression matches with second case 12 and therefore the commands for the corresponding case got executed.

Example 2: Bash case statement with default * pattern

In this example, we shall look into a scenario where there is a default case when no previous cases has a match.

</>
Copy
#!/bin/bash

time=15

# if condition is true
case $time in
9)
	echo Good Morning!
	;;
12)
	echo Good Noon!
	;;
17)
	echo Good Evening!
	;;
21)
	echo Good Night!
	;;
*)
	echo Good Day!
	;;
esac
~$ ./bash-case-default-example 
Good Day!

The expression, does not match to any of the cases but last, default case.

The * pattern should normally be the last branch. If it is placed before more specific patterns, it may match first and prevent the later branches from being reached.

Bash case patterns with | alternatives and wildcard matching

A Bash case branch can match more than one pattern by separating patterns with |. This is useful when different user inputs should run the same command list.

</>
Copy
#!/bin/bash

answer="Y"

case "$answer" in
  y|Y|yes|YES)
    echo "Continue"
    ;;
  n|N|no|NO)
    echo "Stop"
    ;;
  *)
    echo "Please enter yes or no"
    ;;
esac
Continue

Bash case patterns can also use simple wildcard matching. For example, *.txt can match text files and *.sh can match shell scripts. These are shell patterns, not regular expressions.

</>
Copy
#!/bin/bash

file_name="notes.txt"

case "$file_name" in
  *.txt)
    echo "Text file"
    ;;
  *.sh)
    echo "Shell script"
    ;;
  *.jpg|*.jpeg|*.png)
    echo "Image file"
    ;;
  *)
    echo "Unknown file type"
    ;;
esac
Text file

Bash case menu example using read input

One common use of the Bash case statement is a terminal menu. The script reads a value from the user and runs the commands for the matching menu option.

</>
Copy
#!/bin/bash

echo "1) Start backup"
echo "2) Show disk usage"
echo "3) Exit"
read -r -p "Enter choice: " choice

case "$choice" in
  1)
    echo "Starting backup..."
    ;;
  2)
    df -h
    ;;
  3)
    echo "Exiting"
    ;;
  "")
    echo "No choice entered"
    ;;
  *)
    echo "Invalid choice: $choice"
    ;;
esac

The empty string branch "" handles a user pressing Enter without typing a value. The * branch handles every other unmatched input.

Bash case with command substitution $()

The $() syntax in Bash runs a command and substitutes its output. You can use it as the expression for a case statement when the match depends on a command result.

</>
Copy
#!/bin/bash

case "$(uname -s)" in
  Linux)
    echo "Running on Linux"
    ;;
  Darwin)
    echo "Running on macOS"
    ;;
  *)
    echo "Running on another operating system"
    ;;
esac

This form is useful for platform-specific script logic. The case expression is evaluated once, then Bash compares the result against the listed patterns from top to bottom.

When to choose Bash case instead of if elif

Use a Bash case statement when one value is being compared against several possible matches. Use if and elif when each branch needs a different test, such as numeric comparison, file checks, or compound boolean conditions.

Script requirementBetter choiceReason
Match one variable against fixed valuescaseClearer than many elif branches
Match file extensions or wildcard patternscaseShell patterns fit this use case
Compare numbers using -gt or -ltifNumeric tests are condition expressions
Check whether a string is empty with -zif or a dedicated case "" branchBoth work, but -z is explicit for validation

In Bash tests, -z "$value" is true when a string has zero length, and -n "$value" is true when a string has non-zero length. These tests are often used before a case statement when input validation should happen separately from pattern matching.

Common Bash case mistakes in shell scripts

  • Missing esac: The statement must end with esac, which is case written backward.
  • Missing ;; after a branch: Beginner scripts should normally end each matched branch with ;;.
  • Putting * too early: The default pattern should usually be last because it can match almost anything.
  • Treating case patterns as regular expressions: Patterns such as *.txt are shell patterns. Regular expression operators do not work the same way inside a basic case pattern.
  • Not quoting user input: Prefer case "$choice" in for values read from users, files, or command output.

Bash case FAQ

How do you write a case statement in Bash?

Write case "$value" in, add one or more patterns followed by ), place commands under each pattern, end each branch with ;;, and close the statement with esac.

What does * mean in a Bash case statement?

In a Bash case statement, * is a wildcard pattern. When used as the last branch, it acts like a default case for values that did not match earlier patterns.

Can Bash case match multiple values in one branch?

Yes. Use | between patterns. For example, y|Y|yes|YES) can handle several forms of a yes answer in one branch.

Is Bash case the same as a switch statement?

It serves a similar purpose, but the syntax is different. Bash uses case, shell patterns, branch terminators such as ;;, and esac to close the statement.

What does $() do when used with Bash case?

$() performs command substitution. Bash runs the command inside the parentheses and uses its output as the value to match in the case statement.

Editorial QA checklist for this Bash case tutorial

  • Every Bash case example closes with esac.
  • Each beginner-friendly branch ends with ;;.
  • The default * branch is placed after the specific patterns.
  • User input and command substitution examples quote the case expression.
  • Output blocks are marked as output-only, and new Bash examples use PrismJS-compatible language classes.

Bash case statement recap

In this Bash Scripting Tutorial, we have learnt about the syntax of usage of Bash Case statement with example bash scripts.

The main points to remember are: use case when one expression has many possible pattern matches, keep the default * branch last, quote values that come from users or commands, and close the statement with esac. For the complete Bash reference, see the Bash manual section on conditional constructs.