Linux CLI 68 ๐ง operators in shell scripts
#!/bin/bash
# Arithmetic operations
num1=10
num2=5
sum=$(( num1 + num2 ))
difference=$(( num1 - num2 ))
product=$(( num1 * num2 ))
quotient=$(( num1 / num2 ))
remainder=$(( num1 % num2 ))
echo "Sum: $sum"
echo "Difference: $difference"
echo "Product: $product"
echo "Quotient: $quotient"
echo "Remainder: $remainder"
# Relational operations
if [ "$num1" -gt "$num2" ]; then
echo "$num1 is greater than $num2."
elif [ "$num1" -lt "$num2" ]; then
echo "$num1 is less than $num2."
else
echo "$num1 is equal to $num2."
fi
# Logical operations
if [ "$num1" -gt 0 ] && [ "$num2" -gt 0 ]; then
echo "Both numbers are positive."
elif [ "$num1" -lt 0 ] || [ "$num2" -lt 0 ]; then
echo "At least one number is negative."
else
echo "One or both numbers are zero."
fi
# String operations
str1="Hello"
str2="World"
if [ "$str1" = "$str2" ]; then
echo "The strings are equal."
elif [ "$str1" \< "$str2" ]; then
echo "\"$str1\" is less than \"$str2\" in ASCII order."
else
echo "\"$str1\" is greater than \"$str2\" in ASCII order."
fi
# File test operations
if [ -e "/etc/passwd" ]; then
echo "/etc/passwd exists."
fi
if [ -f "/etc/passwd" ]; then
echo "/etc/passwd is a regular file."
fi
if [ -d "/etc" ]; then
echo "/etc is a directory."
fi
# Assignment operations
x=10
y=5
x=$(( x + y ))
echo "After addition, x = $x"
# Bitwise AND operation
num1=60 # Binary: 00111100
num2=13 # Binary: 00001101
and_result=$(( num1 & num2 ))
echo "Bitwise AND of $num1 and $num2 is: $and_result"
# Bitwise OR operation
or_result=$(( num1 | num2 ))
echo "Bitwise OR of $num1 and $num2 is: $or_result"
# Bitwise XOR operation
xor_result=$(( num1 ^ num2 ))
echo "Bitwise XOR of $num1 and $num2 is: $xor_result"
# Bitwise NOT operation (negation)
not_result=$(( ~num1 ))
echo "Bitwise NOT of $num1 is: $not_result"
# Left shift operation
left_shift=$(( num1 << 2 ))
echo "Left shift of $num1 by 2 bits is: $left_shift"
# Right shift operation
right_shift=$(( num1 >> 2 ))
echo "Right shift of $num1 by 2 bits is: $right_shift"
Shell scripts use operators to perform operations on variables, strings, numbers, and files. They fall into a handful of categories โ arithmetic, relational, logical, assignment, file test, string, and bitwise. Knowing which operator to use in which context is half the battle in shell scripting.
Key point: The operator you use depends on where you use it. Inside $((...)) you use C-style operators (+, -, *, /). Inside [ ] you use alphabetic operators (-eq, -lt). Inside [[ ]] you can use either. Mixing them up is the #1 source of bugs.
a – unary, assignment and logical operators in shell scripts
Shell scripts use various operators to perform operations on variables, strings, numbers, and other data types.
Common categories of operators:
| Category | Purpose |
|---|---|
| Unary | Operate on one operand (+, -, !) |
| Arithmetic | Math on numbers (+, -, *, /, %) |
| Relational | Compare numbers or strings (-eq, -lt) |
| Logical | Combine conditions (&&, ||, !) |
| Assignment | Store values (=, +=, -=) |
| File test | Test file properties (-f, -d, -x) |
| String | Compare strings (=, !=, <, >) |
| Bitwise | Operate on individual bits (&, |, ^) |
Unary operators:
“Unary” refers to the number of operands โ these take one operand. There are two unary operators, + and -, which indicate whether a number is positive or negative.
$ x=5
$ echo $(( -x ))
[ -5 ]
$ echo $(( +x ))
[ 5 ]
$ y=-10
$ echo $(( -y ))
[ 10 ]
There’s also the logical NOT !, which negates a condition:
$ [ ! -f /nonexistent ] && echo "not a file"
[ not a file ]
Assignment operators:
| Operator | Meaning | Example |
|---|---|---|
= | Simple assignment | x=10 |
+= | Add and assign | ((x += 5)) |
-= | Subtract and assign | ((x -= 3)) |
*= | Multiply and assign | ((x *= 2)) |
/= | Divide and assign | ((x /= 4)) |
%= | Modulus and assign | ((x %= 3)) |
$ x=10
$ (( x += 5 )); echo $x
[ 15 ]
$ (( x -= 3 )); echo $x
[ 12 ]
$ (( x *= 2 )); echo $x
[ 24 ]
$ (( x /= 4 )); echo $x
[ 6 ]
$ (( x %= 4 )); echo $x
[ 2 ]
Note: The
=inx=10is a variable assignment, not an operator you use inside$(( )). Inside arithmetic, use==for comparison.
Logical operators:
| Operator | Meaning |
|---|---|
&& | Logical AND |
|| | Logical OR |
! | Logical NOT |
$ a=10
$ b=5
$ if [ "$a" -gt 0 ] && [ "$b" -gt 0 ]; then
> echo "Both positive"
> fi
[ Both positive ]
$ if [ "$a" -lt 0 ] || [ "$b" -lt 0 ]; then
> echo "At least one negative"
> else
> echo "Neither negative"
> fi
[ Neither negative ]
$ if [ ! -f /nonexistent ]; then
> echo "File not found"
> fi
[ File not found ]
Short-circuit evaluation:
&& and || are short-circuit โ they stop as soon as the result is determined:
# && โ if the first fails, the second isn't run
$ [ -f /nonexistent ] && echo "never printed"
# || โ if the first succeeds, the second isn't run
$ [ -d /etc ] || echo "never printed"
This makes them useful for conditional execution:
$ command && echo "success" || echo "failed"
Combining logic inside [[ ]]:
$ if [[ $a -gt 0 && $b -gt 0 ]]; then
> echo "Both positive"
> fi
[ Both positive ]
With [[ ]], you don’t need separate brackets for each condition.
b – Arithmetic relational and string operators in shell scripts
Arithmetic operators:
| Operator | Meaning |
|---|---|
+ | Addition |
- | Subtraction |
* | Multiplication |
/ | Division (integer only) |
% | Modulus (remainder) |
** | Exponentiation |
++ | Increment |
-- | Decrement |
$ num1=10
$ num2=5
$ sum=$(( num1 + num2 ))
$ difference=$(( num1 - num2 ))
$ product=$(( num1 * num2 ))
$ quotient=$(( num1 / num2 ))
$ remainder=$(( num1 % num2 ))
$ echo "Sum: $sum"
$ echo "Difference: $difference"
$ echo "Product: $product"
$ echo "Quotient: $quotient"
$ echo "Remainder: $remainder"
[ Sum: 15 ]
[ Difference: 5 ]
[ Product: 50 ]
[ Quotient: 2 ]
[ Remainder: 0 ]
Increment and decrement:
$ i=5
$ (( i++ )); echo $i
[ 6 ]
$ (( i-- )); echo $i
[ 5 ]
$ (( ++i )); echo $i
[ 6 ]
$ (( --i )); echo $i
[ 5 ]
| Form | Meaning |
|---|---|
i++ | Use, then increment (post) |
++i | Increment, then use (pre) |
i-- | Use, then decrement (post) |
--i | Decrement, then use (pre) |
Integer division and modulus:
$ echo $(( 10 / 3 ))
[ 3 ] # truncates, not 3.333
$ echo $(( 10 % 3 ))
[ 1 ] # remainder
$ echo $(( 10 ** 3 ))
[ 1000 ] # exponentiation
Note: Bash arithmetic is integer only. For decimals, use
bcorawk.
Relational operators:
Two syntaxes โ alphabetic (for [ ]) and C-style (for (( )) and [[ ]]):
| Alphabetic | C-style | Meaning |
|---|---|---|
-lt | < | Less than |
-gt | > | Greater than |
-le | <= | Less than or equal |
-ge | >= | Greater than or equal |
-eq | == | Equal to |
-ne | != | Not equal to |
$ num1=10
$ num2=5
$ if [ "$num1" -gt "$num2" ]; then
> echo "$num1 is greater than $num2."
> elif [ "$num1" -lt "$num2" ]; then
> echo "$num1 is less than $num2."
> else
> echo "$num1 is equal to $num2."
> fi
[ 10 is greater than 5. ]
The same in [[ ]] with C-style operators:
$ if [[ $num1 > $num2 ]]; then
> echo "$num1 > $num2"
> fi
[ 10 > 5 ]
โ ๏ธ Warning: Inside
[ ],<and>are redirection operators โ you must escape them (\<,\>). Inside[[ ]], they work bare. This is why[[ ]]is safer.
String operators:
| Operator | Meaning |
|---|---|
= or == | Equal to |
!= | Not equal to |
< | Less than (ASCII) |
> | Greater than (ASCII) |
-z | Empty string |
-n | Non-empty string |
$ str1="Hello"
$ str2="World"
$ if [ "$str1" = "$str2" ]; then
> echo "The strings are equal."
> elif [ "$str1" \< "$str2" ]; then
> echo "\"$str1\" is less than \"$str2\" in ASCII order."
> else
> echo "\"$str1\" is greater than \"$str2\" in ASCII order."
> fi
[ "Hello" is less than "World" in ASCII order. ]
H (72) is less than W (87) in ASCII, so Hello < World.
Always quote strings in [ ]:
# โ Breaks if $name is empty
[ $name = "Alice" ]
# โ
Safe
[ "$name" = "Alice" ]
Numbers vs strings โ the classic bug:
# โ Comparing numbers as strings
$ [ "10" = "10.0" ] && echo "equal" || echo "different"
[ different ]
# โ Comparing strings as numbers
$ [ "abc" -eq "def" ]
[ bash: [: abc: integer expression expected ]
Use = for strings, -eq for numbers. Never mix them.
c – file test and bit operators in shell scripts
File test operators:
| Operator | True if |
|---|---|
-e | File exists |
-f | Regular file |
-d | Directory |
-r | Readable |
-w | Writable |
-x | Executable |
-s | Non-zero size |
-L | Symlink |
-p | Named pipe |
-S | Socket |
$ if [ -e "/etc/passwd" ]; then
> echo "/etc/passwd exists."
> fi
[ /etc/passwd exists. ]
$ if [ -f "/etc/passwd" ]; then
> echo "/etc/passwd is a regular file."
> fi
[ /etc/passwd is a regular file. ]
$ if [ -d "/etc" ]; then
> echo "/etc is a directory."
> fi
[ /etc is a directory. ]
File comparison operators:
| Operator | True if |
|---|---|
f1 -nt f2 | f1 newer than f2 |
f1 -ot f2 | f1 older than f2 |
f1 -ef f2 | Same file (inode) |
$ [ file1.txt -nt file2.txt ] && echo "file1 is newer"
$ [ /etc/passwd -ef /etc/passwd ] && echo "same file"
Combining file tests:
# File exists AND readable
if [ -f "$file" ] && [ -r "$file" ]; then
echo "Can read $file"
fi
# File OR directory
if [ -f "$path" ] || [ -d "$path" ]; then
echo "Path exists"
fi
Bitwise operators:
Bitwise operators perform operations on individual bits of a number.
| Operator | Meaning |
|---|---|
& | Bitwise AND |
| | Bitwise OR |
^ | Bitwise XOR (exclusive OR) |
~ | Bitwise NOT (negation) |
<< | Left shift |
>> | Right shift |
$ num1=60 # Binary: 00111100
$ num2=13 # Binary: 00001101
Bitwise AND (&):
Both bits must be 1 for the result to be 1.
$ and_result=$(( num1 & num2 ))
$ echo "Bitwise AND of $num1 and $num2 is: $and_result"
[ Bitwise AND of 60 and 13 is: 12 ]
60: 00111100
13: 00001101
& 00001100 = 12
Bitwise OR (|):
At least one bit must be 1 for the result to be 1.
$ or_result=$(( num1 | num2 ))
$ echo "Bitwise OR of $num1 and $num2 is: $or_result"
[ Bitwise OR of 60 and 13 is: 61 ]
60: 00111100
13: 00001101
| 00111101 = 61
Bitwise XOR (^):
Bits must be different for the result to be 1.
$ xor_result=$(( num1 ^ num2 ))
$ echo "Bitwise XOR of $num1 and $num2 is: $xor_result"
[ Bitwise XOR of 60 and 13 is: 49 ]
60: 00111100
13: 00001101
^ 00110001 = 49
Bitwise NOT (~):
Flips every bit.
$ not_result=$(( ~num1 ))
$ echo "Bitwise NOT of $num1 is: $not_result"
[ Bitwise NOT of 60 is: -61 ]
Why -61? Because bash uses two’s complement for negative numbers. ~60 = -(60+1) = -61.
Left shift (<<):
Shifts bits to the left by N positions โ equivalent to multiplying by 2^N.
$ left_shift=$(( num1 << 2 ))
$ echo "Left shift of $num1 by 2 bits is: $left_shift"
[ Left shift of 60 by 2 bits is: 240 ]
60 << 2 = 60 ร 4 = 240
Right shift (>>):
Shifts bits to the right by N positions โ equivalent to dividing by 2^N.
$ right_shift=$(( num1 >> 2 ))
$ echo "Right shift of $num1 by 2 bits is: $right_shift"
[ Right shift of 60 by 2 bits is: 15 ]
60 >> 2 = 60 รท 4 = 15
Common uses of bitwise operators:
| Use case | Operator |
|---|---|
| Permission masks | & (test), | (set) |
| Flags | &, |, ^ |
| Power of 2 multiply/divide | <<, >> |
| Toggle bits | ^ |
| Invert bits | ~ |
Practical example โ bitmask flags:
READ=0x01 # 0001
WRITE=0x02 # 0010
EXEC=0x04 # 0100
flags=0
(( flags |= READ )) # set read
(( flags |= EXEC )) # set exec
# flags = 0101 = 5
# Test
(( flags & READ )) && echo "read enabled"
(( flags & WRITE )) && echo "write enabled"
(( flags & EXEC )) && echo "exec enabled"
[ read enabled ]
[ exec enabled ]
Practical example โ permission check:
# Check if a file is world-writable
perms=$(stat -c %a "$file")
if (( 0$perms & 002 )); then
echo "File is world-writable!"
fi
Complete Example Session
# ============================================
# PART 1: ARITHMETIC
# ============================================
$ num1=10
$ num2=5
$ echo $(( num1 + num2 ))
[ 15 ]
$ echo $(( num1 - num2 ))
[ 5 ]
$ echo $(( num1 * num2 ))
[ 50 ]
$ echo $(( num1 / num2 ))
[ 2 ]
$ echo $(( num1 % num2 ))
[ 0 ]
# ============================================
# PART 2: INCREMENT / DECREMENT
# ============================================
$ i=5
$ (( i++ )); echo $i
[ 6 ]
$ (( i-- )); echo $i
[ 5 ]
# ============================================
# PART 3: RELATIONAL
# ============================================
$ if [ "$num1" -gt "$num2" ]; then
> echo "$num1 is greater than $num2."
> elif [ "$num1" -lt "$num2" ]; then
> echo "$num1 is less than $num2."
> else
> echo "$num1 is equal to $num2."
> fi
[ 10 is greater than 5. ]
# ============================================
# PART 4: LOGICAL
# ============================================
$ if [ "$num1" -gt 0 ] && [ "$num2" -gt 0 ]; then
> echo "Both numbers are positive."
> elif [ "$num1" -lt 0 ] || [ "$num2" -lt 0 ]; then
> echo "At least one number is negative."
> else
> echo "One or both numbers are zero."
> fi
[ Both numbers are positive. ]
# ============================================
# PART 5: STRING
# ============================================
$ str1="Hello"
$ str2="World"
$ if [ "$str1" = "$str2" ]; then
> echo "The strings are equal."
> elif [ "$str1" \< "$str2" ]; then
> echo "\"$str1\" is less than \"$str2\" in ASCII order."
> else
> echo "\"$str1\" is greater than \"$str2\" in ASCII order."
> fi
[ "Hello" is less than "World" in ASCII order. ]
# ============================================
# PART 6: FILE TESTS
# ============================================
$ [ -e "/etc/passwd" ] && echo "/etc/passwd exists."
[ /etc/passwd exists. ]
$ [ -f "/etc/passwd" ] && echo "regular file"
[ regular file ]
$ [ -d "/etc" ] && echo "directory"
[ directory ]
# ============================================
# PART 7: ASSIGNMENT
# ============================================
$ x=10
$ y=5
$ x=$(( x + y ))
$ echo "x = $x"
[ x = 15 ]
$ (( x += 5 )); echo $x
[ 20 ]
$ (( x -= 3 )); echo $x
[ 17 ]
$ (( x *= 2 )); echo $x
[ 34 ]
# ============================================
# PART 8: BITWISE AND
# ============================================
$ num1=60
$ num2=13
$ echo $(( num1 & num2 ))
[ 12 ]
# ============================================
# PART 9: BITWISE OR
# ============================================
$ echo $(( num1 | num2 ))
[ 61 ]
# ============================================
# PART 10: BITWISE XOR
# ============================================
$ echo $(( num1 ^ num2 ))
[ 49 ]
# ============================================
# PART 11: BITWISE NOT
# ============================================
$ echo $(( ~num1 ))
[ -61 ]
# ============================================
# PART 12: LEFT SHIFT
# ============================================
$ echo $(( num1 << 2 ))
[ 240 ]
# ============================================
# PART 13: RIGHT SHIFT
# ============================================
$ echo $(( num1 >> 2 ))
[ 15 ]
# ============================================
# PART 14: BITMASK FLAGS
# ============================================
$ READ=0x01
$ WRITE=0x02
$ EXEC=0x04
$ flags=0
$ (( flags |= READ ))
$ (( flags |= EXEC ))
$ echo "Flags: $flags"
[ Flags: 5 ]
$ (( flags & READ )) && echo "read enabled"
$ (( flags & WRITE )) && echo "write enabled"
$ (( flags & EXEC )) && echo "exec enabled"
[ read enabled ]
[ exec enabled ]
# ============================================
# PART 15: OPERATOR CONTEXTS
# ============================================
# Same comparison, three ways
$ a=10
$ b=5
$ [ "$a" -gt "$b" ] && echo "1: greater"
[ 1: greater ]
$ [[ $a -gt $b ]] && echo "2: greater"
[ 2: greater ]
$ (( a > b )) && echo "3: greater"
[ 3: greater ]
# ============================================
# PART 16: FULL SCRIPT
# ============================================
$ cat > ops.sh << 'EOF'
#!/bin/bash
num1=10
num2=5
sum=$(( num1 + num2 ))
difference=$(( num1 - num2 ))
product=$(( num1 * num2 ))
quotient=$(( num1 / num2 ))
remainder=$(( num1 % num2 ))
echo "Sum: $sum"
echo "Difference: $difference"
echo "Product: $product"
echo "Quotient: $quotient"
echo "Remainder: $remainder"
if [ "$num1" -gt "$num2" ]; then
echo "$num1 is greater than $num2."
elif [ "$num1" -lt "$num2" ]; then
echo "$num1 is less than $num2."
else
echo "$num1 is equal to $num2."
fi
if [ "$num1" -gt 0 ] && [ "$num2" -gt 0 ]; then
echo "Both numbers are positive."
elif [ "$num1" -lt 0 ] || [ "$num2" -lt 0 ]; then
echo "At least one number is negative."
else
echo "One or both numbers are zero."
fi
str1="Hello"
str2="World"
if [ "$str1" = "$str2" ]; then
echo "The strings are equal."
elif [ "$str1" \< "$str2" ]; then
echo "\"$str1\" is less than \"$str2\" in ASCII order."
else
echo "\"$str1\" is greater than \"$str2\" in ASCII order."
fi
if [ -e "/etc/passwd" ]; then
echo "/etc/passwd exists."
fi
if [ -f "/etc/passwd" ]; then
echo "/etc/passwd is a regular file."
fi
if [ -d "/etc" ]; then
echo "/etc is a directory."
fi
x=10
y=5
x=$(( x + y ))
echo "After addition, x = $x"
num1=60
num2=13
and_result=$(( num1 & num2 ))
echo "Bitwise AND of $num1 and $num2 is: $and_result"
or_result=$(( num1 | num2 ))
echo "Bitwise OR of $num1 and $num2 is: $or_result"
xor_result=$(( num1 ^ num2 ))
echo "Bitwise XOR of $num1 and $num2 is: $xor_result"
not_result=$(( ~num1 ))
echo "Bitwise NOT of $num1 is: $not_result"
left_shift=$(( num1 << 2 ))
echo "Left shift of $num1 by 2 bits is: $left_shift"
right_shift=$(( num1 >> 2 ))
echo "Right shift of $num1 by 2 bits is: $right_shift"
EOF
$ chmod +x ops.sh
$ ./ops.sh
[ Sum: 15 ]
[ Difference: 5 ]
[ Product: 50 ]
[ Quotient: 2 ]
[ Remainder: 0 ]
[ 10 is greater than 5. ]
[ Both numbers are positive. ]
[ "Hello" is less than "World" in ASCII order. ]
[ /etc/passwd exists. ]
[ /etc/passwd is a regular file. ]
[ /etc is a directory. ]
[ After addition, x = 15 ]
[ Bitwise AND of 60 and 13 is: 12 ]
[ Bitwise OR of 60 and 13 is: 61 ]
[ Bitwise XOR of 60 and 13 is: 49 ]
[ Bitwise NOT of 60 is: -61 ]
[ Left shift of 60 by 2 bits is: 240 ]
[ Right shift of 60 by 2 bits is: 15 ]
Quick Reference
Operator Categories
| Category | Operators | Context |
|---|---|---|
| Unary | +, -, ! | $(( )), [ ] |
| Arithmetic | + - * / % ** | $(( )) |
| Increment | ++, -- | $(( )) |
| Relational (num) | -eq -ne -lt -le -gt -ge | [ ] |
| Relational (C) | == != < <= > >= | (( )), [[ ]] |
| Logical | &&, ||, ! | anywhere |
| Assignment | = += -= *= /= %= | shell / (( )) |
| String | = != < > -z -n | [ ], [[ ]] |
| File test | -e -f -d -r -w -x -s -L | [ ], [[ ]] |
| File compare | -nt -ot -ef | [ ], [[ ]] |
| Bitwise | & | ^ ~ << >> | $(( )) |
Arithmetic Operators
| Operator | Meaning | Example |
|---|---|---|
+ | Addition | $((a + b)) |
- | Subtraction | $((a - b)) |
* | Multiplication | $((a * b)) |
/ | Integer division | $((a / b)) |
% | Modulus | $((a % b)) |
** | Exponentiation | $((a ** b)) |
++ | Increment | ((i++)) |
-- | Decrement | ((i--)) |
Relational Operators
| Alphabetic | C-style | Meaning |
|---|---|---|
-eq | == | Equal |
-ne | != | Not equal |
-lt | < | Less than |
-le | <= | Less or equal |
-gt | > | Greater than |
-ge | >= | Greater or equal |
String Operators
| Operator | Meaning |
|---|---|
= / == | Equal |
!= | Not equal |
< | Less (ASCII) |
> | Greater (ASCII) |
-z | Empty |
-n | Non-empty |
File Test Operators
| Operator | True if |
|---|---|
-e | Exists |
-f | Regular file |
-d | Directory |
-r | Readable |
-w | Writable |
-x | Executable |
-s | Non-empty |
-L | Symlink |
Bitwise Operators
| Operator | Meaning | Example |
|---|---|---|
& | AND | $((a & b)) |
| | OR | $((a | b)) |
^ | XOR | $((a ^ b)) |
~ | NOT | $((~a)) |
<< | Left shift | $((a << 2)) |
>> | Right shift | $((a >> 2)) |
Logical Operators
| Operator | Meaning |
|---|---|
&& | AND |
|| | OR |
! | NOT |
Best Practices
โ Do This:
# Use arithmetic operators inside $(( ))
sum=$(( a + b )) # โ
# Use -eq/-lt for numeric comparison in [ ]
if [ "$a" -gt "$b" ]; then ...; fi # โ
# Use C-style in [[ ]] or (( ))
if [[ $a > $b ]]; then ...; fi # โ
if (( a > b )); then ...; fi # โ
# Quote variables in [ ]
if [ "$str" = "value" ]; then ...; fi # โ
# Escape < and > in [ ]
if [ "$a" \< "$b" ]; then ...; fi # โ
# Use == for numbers in [[ ]] or (( ))
if [[ $a == $b ]]; then ...; fi # โ
# Use bitwise masks for flags
(( flags |= READ )) # โ
# Combine file tests with &&
if [ -f "$f" ] && [ -r "$f" ]; then ...; fi # โ
โ Don’t Do This:
# Don't use = for numbers
if [ "$a" = 5 ]; then ...; fi # โ ๏ธ string compare
if [ "$a" -eq 5 ]; then ...; fi # โ
# Don't use -eq for strings
if [ "$name" -eq "Alice" ]; then ...; fi # โ error
if [ "$name" = "Alice" ]; then ...; fi # โ
# Don't use < > unescaped in [ ]
if [ "$a" > "$b" ]; then ...; fi # โ creates file "b"
if [ "$a" \> "$b" ]; then ...; fi # โ
if [[ $a > $b ]]; then ...; fi # โ
# Don't forget spaces around [ ]
if [$a -gt 0]; then ...; fi # โ syntax error
# Don't mix arithmetic and string contexts
echo $(( name )) # โ variable must be a number
# Don't expect floating point
echo $(( 10 / 3 )) # โ gives 3, not 3.33
echo "scale=2; 10/3" | bc # โ
# Don't use && inside [ ]
if [ "$a" -gt 0 && "$b" -gt 0 ]; then ...; fi # โ
if [ "$a" -gt 0 ] && [ "$b" -gt 0 ]; then ...; fi # โ
if [[ $a -gt 0 && $b -gt 0 ]]; then ...; fi # โ
# Don't confuse = with == inside (( ))
(( x = 5 )) # โ assignment
(( x == 5 )) # โ
comparison
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
= for numbers | String compare | Use -eq |
-eq for strings | Error | Use = |
< unescaped in [ ] | Redirection | \< or use [[ ]] |
&& inside [ ] | Syntax error | Separate brackets or use [[ ]] |
| Floating point | Truncated | Use bc or awk |
| Missing spaces | Syntax error | [ -f f ] |
| Unquoted variable | Word splitting | Quote it |
= vs == in (( )) | Assignment vs compare | Use == for compare |
Real-World Examples
1. Arithmetic Operations
#!/bin/bash
num1=10
num2=5
sum=$(( num1 + num2 ))
difference=$(( num1 - num2 ))
product=$(( num1 * num2 ))
quotient=$(( num1 / num2 ))
remainder=$(( num1 % num2 ))
echo "Sum: $sum"
echo "Difference: $difference"
echo "Product: $product"
echo "Quotient: $quotient"
echo "Remainder: $remainder"
[ Sum: 15 ]
[ Difference: 5 ]
[ Product: 50 ]
[ Quotient: 2 ]
[ Remainder: 0 ]
2. Relational Operations
#!/bin/bash
num1=10
num2=5
if [ "$num1" -gt "$num2" ]; then
echo "$num1 is greater than $num2."
elif [ "$num1" -lt "$num2" ]; then
echo "$num1 is less than $num2."
else
echo "$num1 is equal to $num2."
fi
[ 10 is greater than 5. ]
3. Logical Operations
#!/bin/bash
num1=10
num2=5
if [ "$num1" -gt 0 ] && [ "$num2" -gt 0 ]; then
echo "Both numbers are positive."
elif [ "$num1" -lt 0 ] || [ "$num2" -lt 0 ]; then
echo "At least one number is negative."
else
echo "One or both numbers are zero."
fi
[ Both numbers are positive. ]
4. String Comparison
#!/bin/bash
str1="Hello"
str2="World"
if [ "$str1" = "$str2" ]; then
echo "The strings are equal."
elif [ "$str1" \< "$str2" ]; then
echo "\"$str1\" is less than \"$str2\" in ASCII order."
else
echo "\"$str1\" is greater than \"$str2\" in ASCII order."
fi
[ "Hello" is less than "World" in ASCII order. ]
5. File Tests
#!/bin/bash
if [ -e "/etc/passwd" ]; then
echo "/etc/passwd exists."
fi
if [ -f "/etc/passwd" ]; then
echo "/etc/passwd is a regular file."
fi
if [ -d "/etc" ]; then
echo "/etc is a directory."
fi
6. Assignment
#!/bin/bash
x=10
y=5
x=$(( x + y ))
echo "After addition, x = $x"
[ After addition, x = 15 ]
7. Bitwise AND
#!/bin/bash
num1=60
num2=13
echo "Bitwise AND: $(( num1 & num2 ))"
[ Bitwise AND: 12 ]
8. Bitwise OR
#!/bin/bash
num1=60
num2=13
echo "Bitwise OR: $(( num1 | num2 ))"
[ Bitwise OR: 61 ]
9. Bitwise XOR
#!/bin/bash
num1=60
num2=13
echo "Bitwise XOR: $(( num1 ^ num2 ))"
[ Bitwise XOR: 49 ]
10. Bitwise NOT
#!/bin/bash
num1=60
echo "Bitwise NOT: $(( ~num1 ))"
[ Bitwise NOT: -61 ]
11. Left Shift
#!/bin/bash
num1=60
echo "Left shift: $(( num1 << 2 ))"
[ Left shift: 240 ]
12. Right Shift
#!/bin/bash
num1=60
echo "Right shift: $(( num1 >> 2 ))"
[ Right shift: 15 ]
13. Increment and Decrement
#!/bin/bash
i=5
(( i++ )); echo "$i"
(( i-- )); echo "$i"
(( ++i )); echo "$i"
(( --i )); echo "$i"
[ 6 ]
[ 5 ]
[ 6 ]
[ 5 ]
14. Compound Assignment
#!/bin/bash
x=10
(( x += 5 )); echo "$x"
(( x -= 3 )); echo "$x"
(( x *= 2 )); echo "$x"
(( x /= 4 )); echo "$x"
[ 15 ]
[ 12 ]
[ 24 ]
[ 6 ]
15. Bitmask Flags
#!/bin/bash
READ=0x01
WRITE=0x02
EXEC=0x04
flags=0
(( flags |= READ ))
(( flags |= EXEC ))
(( flags & READ )) && echo "read enabled"
(( flags & WRITE )) && echo "write enabled"
(( flags & EXEC )) && echo "exec enabled"
[ read enabled ]
[ exec enabled ]
16. Test If Power of 2
#!/bin/bash
n=32
if (( n > 0 && (n & (n - 1)) == 0 )); then
echo "$n is a power of 2"
fi
[ 32 is a power of 2 ]
17. Swap Two Numbers
#!/bin/bash
a=5
b=10
a=$(( a ^ b ))
b=$(( a ^ b ))
a=$(( a ^ b ))
echo "a=$a b=$b"
[ a=10 b=5 ]
18. Numeric Validation
#!/bin/bash
read -p "Enter a number: " n
if [[ "$n" =~ ^-?[0-9]+$ ]]; then
echo "Valid integer: $n"
else
echo "Not an integer"
fi
19. Even/Odd
#!/bin/bash
n=7
if (( n % 2 == 0 )); then
echo "even"
else
echo "odd"
fi
[ odd ]
20. Full Script
#!/bin/bash
num1=10
num2=5
sum=$(( num1 + num2 ))
difference=$(( num1 - num2 ))
product=$(( num1 * num2 ))
quotient=$(( num1 / num2 ))
remainder=$(( num1 % num2 ))
echo "Sum: $sum"
echo "Difference: $difference"
echo "Product: $product"
echo "Quotient: $quotient"
echo "Remainder: $remainder"
if [ "$num1" -gt "$num2" ]; then
echo "$num1 is greater than $num2."
elif [ "$num1" -lt "$num2" ]; then
echo "$num1 is less than $num2."
else
echo "$num1 is equal to $num2."
fi
if [ "$num1" -gt 0 ] && [ "$num2" -gt 0 ]; then
echo "Both numbers are positive."
elif [ "$num1" -lt 0 ] || [ "$num2" -lt 0 ]; then
echo "At least one number is negative."
else
echo "One or both numbers are zero."
fi
str1="Hello"
str2="World"
if [ "$str1" = "$str2" ]; then
echo "The strings are equal."
elif [ "$str1" \< "$str2" ]; then
echo "\"$str1\" is less than \"$str2\" in ASCII order."
else
echo "\"$str1\" is greater than \"$str2\" in ASCII order."
fi
if [ -e "/etc/passwd" ]; then
echo "/etc/passwd exists."
fi
if [ -f "/etc/passwd" ]; then
echo "/etc/passwd is a regular file."
fi
if [ -d "/etc" ]; then
echo "/etc is a directory."
fi
x=10
y=5
x=$(( x + y ))
echo "After addition, x = $x"
num1=60
num2=13
and_result=$(( num1 & num2 ))
echo "Bitwise AND of $num1 and $num2 is: $and_result"
or_result=$(( num1 | num2 ))
echo "Bitwise OR of $num1 and $num2 is: $or_result"
xor_result=$(( num1 ^ num2 ))
echo "Bitwise XOR of $num1 and $num2 is: $xor_result"
not_result=$(( ~num1 ))
echo "Bitwise NOT of $num1 is: $not_result"
left_shift=$(( num1 << 2 ))
echo "Left shift of $num1 by 2 bits is: $left_shift"
right_shift=$(( num1 >> 2 ))
echo "Right shift of $num1 by 2 bits is: $right_shift"
Visual: Operator Categories
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Operator categories โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ARITHMETIC โ โ
โ โ + - * / % ** ++ -- โ โ
โ โ โ inside $(( )) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ RELATIONAL (numeric) โ โ
โ โ -eq -ne -lt -le -gt -ge โ โ
โ โ โ inside [ ] โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ RELATIONAL (C-style) โ โ
โ โ == != < <= > >= โ โ
โ โ โ inside (( )) and [[ ]] โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ LOGICAL โ โ
โ โ && || ! โ โ
โ โ โ combine conditions โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ STRING โ โ
โ โ = != < > -z -n โ โ
โ โ โ compare text โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ FILE TEST โ โ
โ โ -e -f -d -r -w -x -s -L โ โ
โ โ โ test files and dirs โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ BITWISE โ โ
โ โ & | ^ ~ << >> โ โ
โ โ โ manipulate bits โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Bitwise Operations
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ num1 = 60 = 00111100 โ
โ num2 = 13 = 00001101 โ
โ โ
โ AND & 00111100 โ
โ 00001101 โ
โ โโโโโโโโ โ
โ 00001100 = 12 โ
โ โ
โ OR | 00111100 โ
โ 00001101 โ
โ โโโโโโโโ โ
โ 00111101 = 61 โ
โ โ
โ XOR ^ 00111100 โ
โ 00001101 โ
โ โโโโโโโโ โ
โ 00110001 = 49 โ
โ โ
โ NOT ~ 00111100 โ
โ โโโโโโโโ โ
โ 11000011 = -61 (two's complement) โ
โ โ
โ << 2 00111100 << 2 = 11110000 = 240 โ
โ >> 2 00111100 >> 2 = 00001111 = 15 โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Operator Contexts
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Which operator where? โ
โ โ
โ $(( a + b )) arithmetic: + - * / % โ
โ comparison: == != < > โ
โ bitwise: & | ^ ~ << >>โ
โ โ
โ [ "$a" -gt "$b" ] numeric: -eq -ne -lt ... โ
โ string: = != -z -n โ
โ file: -f -d -e ... โ
โ โ
โ [[ $a > $b ]] C-style: == != < > โ
โ also numeric and string โ
โ && || inside โ
โ โ
โ (( a > b )) C-style only โ
โ no strings โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Category | Operators | Use in |
|---|---|---|
| Unary | + - ! | $(( )), [ ] |
| Arithmetic | + - * / % ** | $(( )) |
| Increment | ++ -- | (( )) |
| Assignment | = += -= *= /= %= | shell, (( )) |
| Numeric relational | -eq -ne -lt -le -gt -ge | [ ] |
| C-style relational | == != < <= > >= | (( )), [[ ]] |
| Logical | && || ! | conditions |
| String | = != < > -z -n | [ ], [[ ]] |
| File test | -e -f -d -r -w -x -s -L | [ ], [[ ]] |
| File compare | -nt -ot -ef | [ ], [[ ]] |
| Bitwise | & | ^ ~ << >> | $(( )) |
Key takeaways:
- Arithmetic operators work in
$(( ))โ+,-,*,/,%,** - Numeric comparisons use
-eq,-lt, etc. in[ ];==,<, etc. in(( ))and[[ ]] - String comparisons use
=,!=,<,>โ always quote variables in[ ] - File tests use
-f,-d,-e,-r,-w,-xโ check file properties - Logical operators
&&,||,!combine conditions โ use separate[ ]brackets or[[ ]] - Bitwise operators
&,|,^,~,<<,>>manipulate bits โ useful for flags and masks - Increment and decrement
++and--work in(( )) - Compound assignment
+=,-=,*=,/=combine math with assignment - Integer only โ no floating point in
$(( )); usebcorawk - Watch out for
=vs-eqand=vs==โ mixing them is the most common bug - Escape
<and>in[ ]or use[[ ]]
Remember: The right operator depends on the context. Inside $(( )), use math symbols. Inside [ ], use alphabetic test operators. Inside (( )) and [[ ]], use C-style. And always match the operator to the type โ -eq for numbers, = for strings, -f for files. Get this right, and your conditions will be correct and portable.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!