
Logical Operators and Comparison in Bash
When scripting in Bash, logical operators and comparisons let you make decisions based on one or more conditions. They’re fundamental to writing powerful, flexible, and intelligent scripts.
Comparison Operators
Comparison operators evaluate relationships between values. They’re essential for conditional statements like if
, elif
, and while
.
String Comparison Operators
Operator Meaning Example ==
Strings are equal if [ "$a" == "$b" ]
!=
Strings are not equal if [ "$a" != "$b" ]
<
String is less (alphabetically) if [[ "$a" < "$b" ]]
>
String is greater (alphabetically) if [[ "$a" > "$b" ]]
-z
String is empty if [ -z "$a" ]
-n
String is not empty if [ -n "$a" ]
Note: Always quote your variables in comparisons ("$var"
) to avoid errors if they’re empty or contain spaces.
Numeric Comparison Operators
Use arithmetic operators inside [ ]
or (( ))
:
Operator Meaning Example -eq
Equal [ $a -eq $b ]
-ne
Not equal [ $a -ne $b ]
-lt
Less than [ $a -lt $b ]
-le
Less than or equal [ $a -le $b ]
-gt
Greater than [ $a -gt $b ]
-ge
Greater than or equal [ $a -ge $b ]
Modern syntax allows (( ))
for numeric comparisons:
$$
if (( a > b )); then
echo “a is greater than b”
fi
$$
Logical Operators
Logical operators let you combine multiple conditions in a single test.
AND
Syntax Description [ condition1 ] && [ condition2 ]
Both conditions must be true [[ condition1 && condition2 ]]
Same as above, safer for complex tests
Example:
$$
if [[ $age -ge 18 && $age -le 65 ]]; then
echo “Eligible for work”
fi
$$
OR
Syntax Description [ condition1 ] || [ condition2 ]
At least one condition must be true `[[ condition1
Example:
$$
if [[ “$choice” == “yes” || “$choice” == “y” ]]; then
echo “Proceeding…”
fi
$$
NOT
Negates a condition.
Syntax Description ! condition
True if condition is false
Example:
$$
if [ ! -f “important.txt” ]; then
echo “File not found!”
fi
$$
Practical Examples
Check for valid user input:
$$
read -p “Enter a number between 1 and 5: ” num
if [[ $num -ge 1 && $num -le 5 ]]; then
echo “You entered $num.”
else
echo “Invalid input.”
fi
$$
Check if a file exists or a directory exists:
$$
if [[ -f “myfile.txt” || -d “mydir” ]]; then
echo “File or directory exists.”
else
echo “Neither found.”
fi
$$
Using NOT to check if a command is unavailable:
$$
if ! command -v git &>/dev/null; then
echo “Git is not installed!”
fi
$$
Advanced: Using (( ))
with Arithmetic & Logical
You can combine arithmetic and logic inside (( ))
:
$$
a=8
b=4
if (( a > b && a < 20 )); then
echo “a is between b and 20”
fi
$$
Tips
Always quote strings in [
or [[ ]]
to avoid errors with empty/space-containing variables.
Prefer [[ ]]
over [ ]
for more advanced conditionals (like &&
, ||
, <
, >
for strings).
Remember that [[ ]]
and (( ))
cannot be used in POSIX-sh-only scripts (they’re Bash extensions).
Arithmetic Comparison Operators
While string comparisons use =, !=, and so on, Bash provides specific arithmetic comparison operators to work with numbers inside [ ] or test. These include:
Operator Meaning Example
-eq - Equal - [ “$a” -eq “$b” ]
-ne - Not equal - [ “$a” -ne “$b” ]
-lt - Less than - [ “$a” -lt “$b” ]
-le - Less than or equal - [ “$a” -le “$b” ]
-gt - Greater than - [ “$a” -gt “$b” ]
-ge - Greater or equal - [ “$a” -ge “$b” ]
Use case:
Check if a server’s load average exceeds a threshold:
load=3
threshold=5
if [ “$load” -gt “$threshold” ]; then
echo “Warning: High load average!”
fi
[[ ]] vs [ ] — Why Double Brackets Rock
Bash introduced [[ ]] as an enhanced conditional expression syntax. It offers:
Safer variable evaluation (no word splitting or pathname expansion).
Support for regex with =~.
Easier logical operations with && and ||.
Example:
if [[ “$input” == “yes” || “$input” == “y” ]]; then
echo “Proceeding…”
fi
Best practice: Prefer [[ ]] in modern scripts when possible.
Pattern Matching with [[ ]]
With [[ ]], you can compare strings against wildcard patterns (globs) natively, which isn’t possible with single [ ]:
file=“report_2025.txt”
if [[ $file == *.txt ]]; then
echo “Text file detected!”
fi
This makes it easy to handle filenames, logs, or user input that follows patterns.
Complex Conditions with Combined Logical Operators
You can nest logical expressions for fine-grained control:
if [[ ( $age -ge 18 && $citizen == “yes” ) || $guardian_approval == “yes” ]]; then
echo “Allowed entry.”
else
echo “Entry denied.”
fi
This lets you build complex rules in a single readable statement.
Return Status & Short-Circuit Behavior
Bash logical operators short-circuit just like in programming languages:
cmd1 && cmd2: If cmd1 fails (non-zero exit), cmd2 will not run.
cmd1 || cmd2: If cmd1 succeeds (zero exit), cmd2 will not run.
Understanding this is key for efficient, reliable scripts.
Safety Tips: Quote Your Variables!
Always quote variables inside conditionals:
if [[ “$filename” == *.sh ]]; then
echo “Shell script found.”
fi
Why? Without quotes, variables with spaces or empty values can break your script, or even cause dangerous unexpected behavior.