Bash Scripting
String Comparison
If Statements
Programming
Linux

How do I compare two string variables in an 'if' statement in Bash?

Master System Design with Codemia

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

Introduction

In Bash, the usual way to compare two strings in an if statement is with [[ ... ]] and ==. It is readable, safe for most scripting cases, and avoids several quoting problems that happen more easily with the older [ ... ] form.

The short answer looks like this:

bash
if [[ "$a" == "$b" ]]; then
  echo "equal"
fi

But there are a few important details behind that pattern.

The Safest Everyday Form

For plain equality in Bash, prefer:

bash
1#!/usr/bin/env bash
2
3a="hello world"
4b="hello world"
5
6if [[ "$a" == "$b" ]]; then
7  echo "Strings are equal"
8else
9  echo "Strings are different"
10fi

Why this form is good:

  • '[[ ... ]] is Bash's modern test syntax'
  • quoting variables keeps spaces intact
  • '== reads naturally for equality'

The older single-bracket syntax also works:

bash
if [ "$a" = "$b" ]; then
  echo "equal"
fi

But when you are writing specifically for Bash, [[ ... ]] is usually the better default.

Inequality and Empty Strings

To check inequality:

bash
if [[ "$a" != "$b" ]]; then
  echo "Strings are different"
fi

To check whether a string is empty:

bash
if [[ -z "$a" ]]; then
  echo "a is empty"
fi

To check whether it is non-empty:

bash
if [[ -n "$a" ]]; then
  echo "a has content"
fi

These are common alongside equality checks in real shell scripts.

Quoting Still Matters

Even inside [[ ... ]], quote variable expansions unless you intentionally want pattern behavior.

Good:

bash
if [[ "$user_input" == "$expected" ]]; then
  echo "match"
fi

Potentially surprising:

bash
if [[ $user_input == $expected ]]; then
  echo "match"
fi

If one side contains wildcard characters, the unquoted form can behave like pattern matching rather than literal equality.

Pattern Matching Is a Different Feature

Inside [[ ... ]], the right-hand side of == can be a pattern if unquoted:

bash
1file="report.txt"
2
3if [[ "$file" == *.txt ]]; then
4  echo "text file"
5fi

That is useful, but it is not the same as comparing two literal strings. If you want literal equality, quote both sides.

Case-Insensitive Comparison

Bash comparisons are case-sensitive by default. If you want case-insensitive comparison, normalize both strings first:

bash
1a="Hello"
2b="hello"
3
4if [[ "${a,,}" == "${b,,}" ]]; then
5  echo "equal ignoring case"
6fi

The ${var,,} expansion converts the value to lowercase in Bash.

Lexicographic Comparison

For ordering comparisons, use [[ ... ]] with < and >:

bash
if [[ "$a" < "$b" ]]; then
  echo "$a comes before $b"
fi

Do not confuse this with numeric comparison. For numbers, use -lt, -gt, and related operators, or Bash arithmetic syntax.

A Small Reusable Example

Here is a script that demonstrates the common cases:

bash
1#!/usr/bin/env bash
2
3left="$1"
4right="$2"
5
6if [[ -z "$left" || -z "$right" ]]; then
7  echo "Provide two strings"
8  exit 1
9fi
10
11if [[ "$left" == "$right" ]]; then
12  echo "Exact match"
13elif [[ "${left,,}" == "${right,,}" ]]; then
14  echo "Match ignoring case"
15else
16  echo "Different strings"
17fi

That is a realistic pattern for command-line validation.

Common Pitfalls

The biggest pitfall is forgetting to quote variables and then getting strange behavior from spaces or wildcard characters.

Another common mistake is mixing string and numeric operators. == compares strings. It does not do numeric comparison.

People also forget that [[ "$x" == pattern ]] behaves differently from [[ "$x" == "$pattern" ]] when the right side contains wildcard characters. The first can be pattern matching, the second is literal comparison.

Finally, if you need POSIX sh portability rather than Bash specifically, stick to [ "$a" = "$b" ] instead of Bash-only features.

Summary

  • In Bash, the usual string comparison form is [[ "$a" == "$b" ]].
  • Use != for inequality and -z or -n for empty-string checks.
  • Quote variables unless you intentionally want pattern matching.
  • Normalize case when you need case-insensitive comparison.
  • Use Bash string operators for strings and numeric operators for numbers.

Course illustration
Course illustration

All Rights Reserved.