Bash Scripting
String Manipulation
Programming
Command Line
Coding Tips

In Bash, how can I check if a string begins with some value?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Checking whether a string starts with a prefix is a small task, but it appears everywhere in shell scripts: command dispatch, file filtering, option parsing, and log inspection. In Bash, the best solution is usually a built-in pattern match because it is fast, readable, and avoids spawning extra processes.

Prefix Checks with Bash Pattern Matching

The simplest approach uses [[ ... ]] with a glob-style pattern. Bash expands the pattern on the right side of == as a string match, not as a regular expression.

bash
1#!/usr/bin/env bash
2
3value="feature/login"
4prefix="feature/"
5
6if [[ "$value" == "$prefix"* ]]; then
7  echo "starts with prefix"
8else
9  echo "does not start with prefix"
10fi

This is usually the most idiomatic Bash answer. It works well when the prefix is literal text and you want the shortest, clearest check.

Two details matter here. First, keep the entire comparison inside [[ ... ]], not [ ... ], because the older single-bracket test does not support the same pattern behavior safely. Second, quote the variable that holds the input string. That prevents word splitting and other unwanted shell behavior.

If the prefix is fixed text and not a pattern, quoting the prefix variable is fine. The trailing * still acts as the wildcard that means "anything after this prefix."

Using case for Multiple Prefixes

When the script has to branch on several possible prefixes, case scales better than stacking many if statements. It also reads like a dispatcher rather than a boolean puzzle.

bash
1#!/usr/bin/env bash
2
3path="/api/users/42"
4
5case "$path" in
6  /api/*)
7    echo "API request"
8    ;;
9  /admin/*)
10    echo "admin request"
11    ;;
12  *)
13    echo "other request"
14    ;;
15esac

This is especially useful in shell scripts that route commands, classify file names, or parse lightweight protocols. For one prefix, [[ ... ]] is usually shorter. For many prefixes, case is easier to maintain.

Regex Checks with =~

If you need more control than a simple prefix, Bash also supports regular expressions through =~. A caret means "start of string," which makes it appropriate for anchored prefix checks.

bash
1#!/usr/bin/env bash
2
3value="release-2026-03"
4
5if [[ "$value" =~ ^release-[0-9]{4}-[0-9]{2}$ ]]; then
6  echo "matched release pattern"
7else
8  echo "did not match"
9fi

Use this when the prefix check is really part of a larger validation rule. If all you need is "starts with text," a glob pattern is usually easier to read than a regex.

One common mistake is quoting the entire regex on the right side of =~. In Bash, that changes how the expression is interpreted and can break the match. Leave the regex unquoted unless you have a specific reason to build it dynamically.

Parameter Expansion for Exact Prefix Removal

Sometimes you do not just want to test a prefix; you want to remove it if it is present. Parameter expansion can do both jobs in one step.

bash
1#!/usr/bin/env bash
2
3value="refs/heads/main"
4trimmed="${value#refs/heads/}"
5
6if [[ "$trimmed" != "$value" ]]; then
7  echo "prefix was present"
8  echo "remaining part: $trimmed"
9else
10  echo "prefix was not present"
11fi

The # operator removes the shortest match from the beginning of the string. This is useful when later script logic needs the rest of the value, not just a yes or no answer.

When External Tools Make Sense

Tools such as grep can also test a prefix:

bash
if printf '%s\n' "$value" | grep -q '^feature/'; then
  echo "starts with prefix"
fi

That works, but it is usually the wrong first choice inside Bash. It spawns another process, which is slower and noisier than built-in matching. External tools make sense when the prefix check is part of a longer text-processing pipeline or when you are already operating on streamed input instead of a shell variable.

Common Pitfalls

Using [ ... ] instead of [[ ... ]] often leads to confusing quoting and pattern-matching behavior. Prefer [[ ... ]] for Bash string tests.

Quoting the wildcard as part of one big string can disable the intended pattern match. Keep the wildcard outside the quoted prefix, as in "$prefix"*.

Reaching for regex too early makes simple scripts harder to read. Use =~ only when you need regex features, not for ordinary literal prefixes.

Calling grep for every string check adds unnecessary process overhead. Built-in Bash matching is usually faster and clearer.

Summary

  • For ordinary prefix checks in Bash, [[ "$value" == "$prefix"* ]] is usually the best answer.
  • Use case when you need to dispatch across several possible prefixes.
  • Use =~ only when the prefix rule is part of a larger regular-expression validation.
  • Parameter expansion is useful when you want to remove a prefix as well as detect it.

Course illustration
Course illustration

All Rights Reserved.