Introduction to Bash Operators
Operators in Bash are symbols that perform specific operations on operands (values or variables). Understanding operators is crucial for writing effective shell scripts, as they enable arithmetic operations, comparisons, logical decisions, and string manipulations.
Key Concepts
- Arithmetic Operators: Perform mathematical calculations
- Comparison Operators: Compare values (strings and numbers)
- Logical Operators: Combine conditions for decision making
- Assignment Operators: Assign and modify values
- Bitwise Operators: Manipulate bits
- String Operators: Work with text data
- File Test Operators: Check file properties
1. Arithmetic Operators
Basic Arithmetic
#!/bin/bash # Basic arithmetic operators a=10 b=3 # Addition sum=$((a + b)) echo "a + b = $sum" # 13 # Subtraction diff=$((a - b)) echo "a - b = $diff" # 7 # Multiplication prod=$((a * b)) echo "a * b = $prod" # 30 # Division (integer) div=$((a / b)) echo "a / b = $div" # 3 (truncates) # Modulo (remainder) mod=$((a % b)) echo "a % b = $mod" # 1 # Exponentiation power=$((a ** b)) echo "a ** b = $power" # 1000 (10^3) # Using expr command (old style) result=$(expr $a + $b) echo "expr: $result" # 13 # Using let command let result=a+b echo "let: $result" # 13
Increment and Decrement
#!/bin/bash x=5 # Post-increment echo $((x++)) # 5 (then x becomes 6) echo "x = $x" # 6 # Pre-increment echo $((++x)) # 7 (x becomes 7, then printed) echo "x = $x" # 7 # Post-decrement echo $((x--)) # 7 (then x becomes 6) echo "x = $x" # 6 # Pre-decrement echo $((--x)) # 5 (x becomes 5, then printed) echo "x = $x" # 5 # Using let for increment/decrement let x++ # Post-increment let ++x # Pre-increment let x-- # Post-decrement let --x # Pre-decrement
Compound Assignment
#!/bin/bash x=10 # Add and assign ((x += 5)) echo "x += 5 -> $x" # 15 # Subtract and assign ((x -= 3)) echo "x -= 3 -> $x" # 12 # Multiply and assign ((x *= 2)) echo "x *= 2 -> $x" # 24 # Divide and assign ((x /= 4)) echo "x /= 4 -> $x" # 6 # Modulo and assign ((x %= 4)) echo "x %= 4 -> $x" # 2 # Using let for compound assignment let "x += 5" let "x -= 3" let "x *= 2" let "x /= 4" let "x %= 4"
Floating Point Arithmetic
#!/bin/bash
# Bash doesn't support floating point natively
# Use bc (basic calculator) for floating point
a=10.5
b=3.2
# Addition with bc
result=$(echo "$a + $b" | bc)
echo "$a + $b = $result" # 13.7
# Division with scale (decimal places)
result=$(echo "scale=2; $a / $b" | bc)
echo "$a / $b = $result" # 3.28
# More complex calculations
result=$(echo "scale=3; sqrt($a)" | bc)
echo "sqrt($a) = $result" # 3.240
# Using bc for comparisons
if (( $(echo "$a > $b" | bc) )); then
echo "$a is greater than $b"
fi
# Alternative: use awk
result=$(awk "BEGIN {print $a / $b}")
echo "awk division: $result"
2. Comparison Operators
Integer Comparison
#!/bin/bash a=10 b=5 c=10 # Equal if [ $a -eq $c ]; then echo "$a equals $c" # 10 equals 10 fi # Not equal if [ $a -ne $b ]; then echo "$a not equal $b" # 10 not equal 5 fi # Greater than if [ $a -gt $b ]; then echo "$a greater than $b" # 10 greater than 5 fi # Less than if [ $b -lt $a ]; then echo "$b less than $a" # 5 less than 10 fi # Greater than or equal if [ $a -ge $c ]; then echo "$a >= $c" # 10 >= 10 fi # Less than or equal if [ $b -le $c ]; then echo "$b <= $c" # 5 <= 10 fi # Using double parentheses (preferred for integers) if (( a == c )); then echo "$a == $c" fi if (( a != b )); then echo "$a != $b" fi if (( a > b )); then echo "$a > $b" fi if (( a < b )); then echo "$a < $b" fi if (( a >= c )); then echo "$a >= $c" fi if (( a <= c )); then echo "$a <= $c" fi
String Comparison
#!/bin/bash str1="hello" str2="world" str3="hello" empty="" # Equal if [ "$str1" = "$str3" ]; then echo "$str1 equals $str3" # hello equals hello fi # Alternative syntax if [[ "$str1" == "$str3" ]]; then echo "$str1 == $str3" fi # Not equal if [ "$str1" != "$str2" ]; then echo "$str1 not equal $str2" # hello not equal world fi # Greater than (lexicographic) if [[ "$str2" > "$str1" ]]; then echo "$str2 > $str1" # world > hello fi # Less than (lexicographic) if [[ "$str1" < "$str2" ]]; then echo "$str1 < $str2" # hello < world fi # Check if string is empty if [ -z "$empty" ]; then echo "String is empty" fi # Check if string is not empty if [ -n "$str1" ]; then echo "String is not empty" fi # Pattern matching if [[ "$str1" == h* ]]; then echo "$str1 starts with h" # hello starts with h fi if [[ "$str1" == *lo ]]; then echo "$str1 ends with lo" # hello ends with lo fi if [[ "$str1" == *ell* ]]; then echo "$str1 contains ell" # hello contains ell fi
3. Logical Operators
AND Operations
#!/bin/bash a=10 b=5 c=20 # Logical AND with test command (old style) if [ $a -gt $b -a $a -lt $c ]; then echo "$a is between $b and $c" # 10 is between 5 and 20 fi # Logical AND with double brackets (preferred) if [[ $a -gt $b && $a -lt $c ]]; then echo "$a is between $b and $c" fi # Using double parentheses if (( a > b && a < c )); then echo "$a is between $b and $c" fi # Multiple conditions name="John" age=25 city="NYC" if [[ "$name" == "John" && $age -gt 18 && "$city" == "NYC" ]]; then echo "John from NYC is an adult" fi # Short-circuit evaluation (second condition only evaluated if first true) if [[ -f "$file" && $(wc -l < "$file") -gt 0 ]]; then echo "File exists and is not empty" fi
OR Operations
#!/bin/bash
day=$(date +%A)
# Logical OR with test command (old style)
if [ "$day" = "Saturday" -o "$day" = "Sunday" ]; then
echo "It's weekend!"
fi
# Logical OR with double brackets (preferred)
if [[ "$day" == "Saturday" || "$day" == "Sunday" ]]; then
echo "It's weekend!"
fi
# Using double parentheses
x=5
if (( x == 5 || x == 10 )); then
echo "x is either 5 or 10"
fi
# Multiple conditions
error_code=$1
if [[ $error_code -eq 404 || $error_code -eq 500 || $error_code -eq 503 ]]; then
echo "Common HTTP error"
fi
# OR with default value
name=${1:-"Guest"} # Use $1 if set, otherwise "Guest"
echo "Hello, $name"
NOT Operations
#!/bin/bash
# Logical NOT with test command
if [ ! -f "$file" ]; then
echo "File does not exist"
fi
# NOT with double brackets
if [[ ! -f "$file" ]]; then
echo "File does not exist"
fi
# NOT with double parentheses
x=5
if (( ! (x > 10) )); then
echo "x is not greater than 10" # x is not greater than 10
fi
# Combining NOT with AND/OR
if [[ ! -f "$file" || ! -r "$file" ]]; then
echo "File either doesn't exist or isn't readable"
fi
# Check if variable is not set
if [ -z "${var+x}" ]; then
echo "var is unset"
fi
# Opposite condition
if ! command -v git >/dev/null 2>&1; then
echo "git is not installed"
fi
Combining Logical Operators
#!/bin/bash # Complex conditions age=25 has_license=true has_insurance=true if [[ $age -ge 18 && $has_license == true && $has_insurance == true ]]; then echo "Can drive legally" fi # Nested conditions with grouping if [[ ($age -ge 18 && $has_license == true) || ($age -ge 16 && $has_permit == true) ]]; then echo "Can operate vehicle" fi # Truth table for logical operators true && true # true true && false # false false && true # false false && false # false true || true # true true || false # true false || true # true false || false # false !true # false !false # true
4. Assignment Operators
Basic Assignment
#!/bin/bash # Simple assignment name="John" age=25 echo "Name: $name, Age: $age" # Multiple assignments (same line) a=5 b=10 c=15 echo "a=$a, b=$b, c=$c" # Assignment with command substitution files=$(ls -la) current_date=$(date) echo "Date: $current_date" # Assignment with arithmetic x=$((5 + 3)) y=$((x * 2)) # Read-only assignment readonly PI=3.14159 # PI=3.14 # This would cause an error
Compound Assignment
#!/bin/bash x=10 # All compound operators work with ((...)) ((x += 5)) # x = x + 5 ((x -= 3)) # x = x - 3 ((x *= 2)) # x = x * 2 ((x /= 4)) # x = x / 4 ((x %= 3)) # x = x % 3 # Using let command let "x += 5" let "x -= 3" let "x *= 2" let "x /= 4" let "x %= 3" # Bitwise compound assignment ((x <<= 1)) # x = x << 1 (left shift) ((x >>= 1)) # x = x >> 1 (right shift) ((x &= 7)) # x = x & 7 (bitwise AND) ((x |= 8)) # x = x | 8 (bitwise OR) ((x ^= 3)) # x = x ^ 3 (bitwise XOR)
5. Bitwise Operators
Basic Bitwise Operations
#!/bin/bash a=5 # 0101 in binary b=3 # 0011 in binary # Bitwise AND result=$((a & b)) echo "$a & $b = $result" # 1 (0001) # Bitwise OR result=$((a | b)) echo "$a | $b = $result" # 7 (0111) # Bitwise XOR result=$((a ^ b)) echo "$a ^ $b = $result" # 6 (0110) # Bitwise NOT (complement) result=$((~a)) echo "~$a = $result" # -6 (two's complement) # Left shift result=$((a << 1)) echo "$a << 1 = $result" # 10 (1010) # Right shift result=$((a >> 1)) echo "$a >> 1 = $result" # 2 (0010) # Practical examples # Check if bit is set bit=2 if (( (a & (1 << bit)) != 0 )); then echo "Bit $bit is set in $a" fi # Set a bit mask=$((1 << 1)) result=$((a | mask)) echo "Set bit 1 in $a: $result" # Clear a bit mask=$((1 << 2)) result=$((a & ~mask)) echo "Clear bit 2 in $a: $result" # Toggle a bit mask=$((1 << 0)) result=$((a ^ mask)) echo "Toggle bit 0 in $a: $result"
Bit Manipulation Examples
#!/bin/bash
# Power of 2 check
is_power_of_two() {
local n=$1
if (( n > 0 && (n & (n-1)) == 0 )); then
return 0
else
return 1
fi
}
for num in 1 2 3 4 16 31 64; do
if is_power_of_two $num; then
echo "$num is a power of 2"
fi
done
# Count set bits (population count)
count_bits() {
local n=$1
local count=0
while (( n )); do
((count += n & 1))
((n >>= 1))
done
echo $count
}
echo "Bits set in 13: $(count_bits 13)" # 1101 -> 3 bits
# Swap two numbers without temporary variable
a=5
b=3
((a ^= b))
((b ^= a))
((a ^= b))
echo "After swap: a=$a, b=$b" # a=3, b=5
# Check if numbers have opposite signs
x=5
y=-3
if (( (x ^ y) < 0 )); then
echo "$x and $y have opposite signs"
fi
# Get absolute value
abs() {
local n=$1
echo $(( (n ^ (n >> 31)) - (n >> 31) ))
}
echo "Absolute of -5: $(abs -5)"
6. String Operators
String Length and Substrings
#!/bin/bash
str="Hello World"
# String length
echo "Length: ${#str}" # 11
# Substring extraction
echo "${str:6}" # World (from position 6)
echo "${str:6:3}" # Wor (3 chars from pos 6)
echo "${str: -5}" # World (last 5 chars)
echo "${str: -5:3}" # Wor (3 chars from end)
# Substring removal (from beginning)
filename="archive.tar.gz"
echo "${filename#*.}" # tar.gz (remove shortest match)
echo "${filename##*.}" # gz (remove longest match)
# Substring removal (from end)
echo "${filename%.*}" # archive.tar (remove shortest from end)
echo "${filename%%.*}" # archive (remove longest from end)
# Replace
str="Hello Hello World"
echo "${str/Hello/Hi}" # Hi Hello World (first match)
echo "${str//Hello/Hi}" # Hi Hi World (all matches)
echo "${str/#Hello/Hi}" # Hi Hello World (beginning)
echo "${str/%World/Everyone}" # Hello Hello Everyone (end)
Pattern Matching and Case Conversion
#!/bin/bash
# Pattern matching
filename="document.txt"
if [[ "$filename" == *.txt ]]; then
echo "Text file"
fi
if [[ "$filename" == doc* ]]; then
echo "Starts with 'doc'"
fi
# Case conversion (Bash 4+)
text="Hello World"
# Lowercase
echo "${text,,}" # hello world
echo "${text,}" # hello World (first char)
# Uppercase
echo "${text^^}" # HELLO WORLD
echo "${text^}" # Hello World (first char)
# Specific character conversion
echo "${text^^[aeiou]}" # HEllO WOrld
# Using tr command
echo "$text" | tr '[:lower:]' '[:upper:]' # HELLO WORLD
echo "$text" | tr '[:upper:]' '[:lower:]' # hello world
7. File Test Operators
File Type Tests
#!/bin/bash file="/etc/passwd" dir="/tmp" link="/usr/bin/python" special="/dev/null" # File existence if [ -e "$file" ]; then echo "$file exists" fi # Regular file if [ -f "$file" ]; then echo "$file is a regular file" fi # Directory if [ -d "$dir" ]; then echo "$dir is a directory" fi # Symbolic link if [ -L "$link" ]; then echo "$link is a symbolic link" fi # Character special file if [ -c "$special" ]; then echo "$special is a character device" fi # Block special file if [ -b "/dev/sda" ]; then echo "/dev/sda is a block device" fi # Socket if [ -S "/var/run/docker.sock" ]; then echo "Docker socket exists" fi # Named pipe if [ -p "/tmp/mypipe" ]; then echo "Pipe exists" fi
Permission Tests
#!/bin/bash file="test.txt" touch "$file" # Readable if [ -r "$file" ]; then echo "$file is readable" fi # Writable if [ -w "$file" ]; then echo "$file is writable" fi # Executable if [ -x "$file" ]; then echo "$file is executable" fi # Setuid if [ -u "/usr/bin/sudo" ]; then echo "sudo has setuid bit" fi # Setgid if [ -g "/usr/bin/wall" ]; then echo "wall has setgid bit" fi # Sticky bit if [ -k "/tmp" ]; then echo "/tmp has sticky bit" fi # Non-empty file echo "content" > "$file" if [ -s "$file" ]; then echo "$file is not empty" fi # Owned by effective user ID if [ -O "$file" ]; then echo "$file is owned by me" fi # Owned by effective group ID if [ -G "$file" ]; then echo "$file is owned by my group" fi
File Comparison Tests
#!/bin/bash file1="test1.txt" file2="test2.txt" echo "Hello" > "$file1" echo "Hello" > "$file2" # Same file (hard links) if [ "$file1" -ef "$file2" ]; then echo "Files are the same (hard links)" else echo "Files are different" fi # Newer modification time touch "$file1" sleep 2 touch "$file2" if [ "$file2" -nt "$file1" ]; then echo "$file2 is newer than $file1" fi # Older modification time if [ "$file1" -ot "$file2" ]; then echo "$file1 is older than $file2" fi # Cleanup rm -f "$file1" "$file2"
8. Redirection Operators
Basic Redirection
#!/bin/bash # Output redirection echo "Hello World" > file.txt # Overwrite echo "Another line" >> file.txt # Append # Input redirection sort < file.txt # Read from file # Error redirection command 2> error.txt # Redirect stderr only command 2>> error.txt # Append stderr # Both stdout and stderr command &> output.txt # Redirect both command &>> output.txt # Append both # Separate streams command > out.txt 2> err.txt # stdout to out.txt, stderr to err.txt # Discard output command > /dev/null 2>&1 # Discard both stdout and stderr # Here document (multiline input) cat << EOF > file.txt This is line 1 This is line 2 This is line 3 EOF # Here string grep "pattern" <<< "This is a test string" # Process substitution diff <(ls dir1) <(ls dir2)
File Descriptor Operations
#!/bin/bash # Duplicate file descriptors exec 3>&1 # Save stdout to fd 3 exec 1> file.txt # Redirect stdout to file echo "This goes to file" exec 1>&3 # Restore stdout exec 3>&- # Close fd 3 # Read from file descriptor exec 3< input.txt # Open file for reading on fd 3 read line <&3 # Read from fd 3 exec 3<&- # Close fd 3 # Custom file descriptors for append exec 3>> log.txt # Open for append echo "Log entry" >&3 # Write to fd 3 exec 3>&- # Close fd 3 # Using /dev/tcp for network operations exec 3<>/dev/tcp/google.com/80 # Open TCP connection echo -e "GET / HTTP/1.0\n\n" >&3 # Send HTTP request cat <&3 # Read response exec 3<&- # Close connection
9. Test Operators
Special Test Constructs
#!/bin/bash
# Double brackets - extended test command
# Supports pattern matching and regex
if [[ "$name" == J* ]]; then
echo "Name starts with J"
fi
if [[ "$email" =~ ^[a-z]+@[a-z]+\.[a-z]+$ ]]; then
echo "Valid email format"
fi
# Double parentheses - arithmetic test
if (( a > b && a < c )); then
echo "a is between b and c"
fi
# Ternary-like operation
result=$(( a > b ? a : b )) # Max of a and b
echo "Max: $result"
# Null coalescing (default value)
name=${1:-"Guest"} # Use $1 if set, else "Guest"
echo "Hello, $name"
# Alternate value
debug=${DEBUG:+1} # Set to 1 if DEBUG is set
Combined Test Examples
#!/bin/bash
# Complex file test
file="test.txt"
if [[ -f "$file" && -r "$file" && -w "$file" && -s "$file" ]]; then
echo "$file is a readable, writable, non-empty regular file"
fi
# String tests with default values
name=${1:-"Guest"}
if [[ -z "$name" || "$name" == "Guest" ]]; then
echo "No name provided, using default"
fi
# Numeric range checks
score=85
if (( score >= 90 )); then
grade="A"
elif (( score >= 80 )); then
grade="B"
elif (( score >= 70 )); then
grade="C"
else
grade="F"
fi
echo "Grade: $grade"
# Multiple condition check
if [[ -f "$file" ]] && command -v gzip >/dev/null; then
gzip "$file"
fi
10. Operator Precedence
Precedence Rules
#!/bin/bash # Operator precedence (highest to lowest) # 1. Post-increment/decrement: var++ var-- # 2. Pre-increment/decrement: ++var --var # 3. Unary minus/plus: - + ! ~ # 4. Exponentiation: ** # 5. Multiplication/Division/Modulo: * / % # 6. Addition/Subtraction: + - # 7. Bitwise shifts: << >> # 8. Relational: < <= > >= # 9. Equality: == != # 10. Bitwise AND: & # 11. Bitwise XOR: ^ # 12. Bitwise OR: | # 13. Logical AND: && # 14. Logical OR: || # 15. Conditional: ? : # 16. Assignment: = += -= *= /= %= &= ^= |= <<= >>= # Examples x=5 y=3 z=2 # Without parentheses (follows precedence) result=$(( x + y * z )) echo "x + y * z = $result" # 5 + (3 * 2) = 11 # With parentheses result=$(( (x + y) * z )) echo "(x + y) * z = $result" # (5 + 3) * 2 = 16 # Complex expression result=$(( x++ * --y + (z << 1) )) echo "Complex result: $result" # Logical operators if [[ $x -gt 0 && $y -gt 0 || $z -gt 0 ]]; then echo "AND has higher precedence than OR" fi # Equivalent with explicit parentheses if [[ ($x -gt 0 && $y -gt 0) || $z -gt 0 ]]; then echo "Same condition with parentheses" fi
Using Parentheses for Clarity
#!/bin/bash
# Always use parentheses to make precedence clear
# Instead of:
if (( a > b && b > c || d == e ))
# Use:
if (( (a > b && b > c) || d == e ))
# Arithmetic with parentheses
result=$(( ( (a + b) * c ) / (d - e) ))
# Command grouping with parentheses (subshell)
(cd /tmp && ls -la) # Changes dir in subshell only
# Command grouping with braces (current shell)
{ cd /tmp && ls -la; } # Changes dir in current shell
# Brace expansion
echo {1..5} # 1 2 3 4 5
echo {a,b,c}{1,2,3} # a1 a2 a3 b1 b2 b3 c1 c2 c3
11. Practical Examples
Calculator Function
#!/bin/bash
# Simple calculator using operators
calculator() {
local a=$1
local op=$2
local b=$3
case $op in
+) echo $((a + b)) ;;
-) echo $((a - b)) ;;
*) echo $((a * b)) ;;
/)
if (( b == 0 )); then
echo "Error: Division by zero"
return 1
fi
echo "scale=2; $a / $b" | bc
;;
%) echo $((a % b)) ;;
^) echo $((a ** b)) ;;
&) echo $((a & b)) ;;
|) echo $((a | b)) ;;
^^) echo $((a ^ b)) ;;
<<) echo $((a << b)) ;;
>>) echo $((a >> b)) ;;
*) echo "Unknown operator: $op"
return 1 ;;
esac
}
# Usage
calculator 10 + 5
calculator 10 '*' 5 # Need to quote *
calculator 10 / 3
calculator 10 '**' 3
Input Validation
#!/bin/bash
# Validate numeric input
validate_number() {
local num=$1
# Check if it's a number
if [[ "$num" =~ ^-?[0-9]+$ ]]; then
return 0
else
return 1
fi
}
# Validate floating point
validate_float() {
local num=$1
if [[ "$num" =~ ^-?[0-9]*\.?[0-9]+$ ]]; then
return 0
else
return 1
fi
}
# Validate email
validate_email() {
local email=$1
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
return 0
else
return 1
fi
}
# Usage
read -p "Enter a number: " input
if validate_number "$input"; then
echo "Valid number"
else
echo "Invalid number"
fi
System Information Script
#!/bin/bash
# Using operators to gather system info
get_system_info() {
# Check if running as root
if [[ $EUID -eq 0 ]]; then
echo "Running as root"
else
echo "Running as regular user"
fi
# Check CPU architecture
arch=$(uname -m)
case "$arch" in
x86_64) echo "64-bit system" ;;
i*86) echo "32-bit system" ;;
arm*) echo "ARM system" ;;
*) echo "Unknown architecture: $arch" ;;
esac
# Check memory (Linux)
if [[ -f /proc/meminfo ]]; then
total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}')
total_mem_mb=$((total_mem / 1024))
if (( total_mem_mb < 1024 )); then
echo "Low memory: ${total_mem_mb}MB"
elif (( total_mem_mb < 4096 )); then
echo "Moderate memory: ${total_mem_mb}MB"
else
echo "Plenty memory: ${total_mem_mb}MB"
fi
fi
# Check disk usage
usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if (( usage > 90 )); then
echo "CRITICAL: Disk usage at ${usage}%"
elif (( usage > 75 )); then
echo "WARNING: Disk usage at ${usage}%"
else
echo "OK: Disk usage at ${usage}%"
fi
}
12. Operator Cheat Sheet
Quick Reference
# Arithmetic Operators + # Addition - # Subtraction * # Multiplication / # Division (integer) % # Modulo ** # Exponentiation ++ # Increment -- # Decrement # Comparison Operators (Integer) -eq # Equal -ne # Not equal -gt # Greater than -ge # Greater or equal -lt # Less than -le # Less or equal # Comparison Operators (String) = # Equal == # Equal ([[ ]]) != # Not equal < # Less than ([[ ]]) > # Greater than ([[ ]]) -z # Empty string -n # Non-empty string # Logical Operators && # Logical AND || # Logical OR ! # Logical NOT -a # AND (test command) -o # OR (test command) # Bitwise Operators & # Bitwise AND | # Bitwise OR ^ # Bitwise XOR ~ # Bitwise NOT << # Left shift >> # Right shift # Assignment Operators = # Simple assignment += # Add and assign -= # Subtract and assign *= # Multiply and assign /= # Divide and assign %= # Modulo and assign &= # Bitwise AND and assign |= # Bitwise OR and assign ^= # Bitwise XOR and assign <<= # Left shift and assign >>= # Right shift and assign # File Test Operators -e # File exists -f # Regular file -d # Directory -L # Symbolic link -r # Readable -w # Writable -x # Executable -s # Non-zero size -O # Owned by user -G # Owned by group -nt # Newer than -ot # Older than -ef # Same file # Redirection Operators > # Redirect stdout (overwrite) >> # Redirect stdout (append) < # Redirect stdin 2> # Redirect stderr &> # Redirect stdout and stderr | # Pipe << # Here document <<< # Here string
Conclusion
Key Takeaways
- Arithmetic Operators: Use
$(( ... ))for integer math,bcfor floating point - Comparison: Use
[[ ... ]]for strings and(( ... ))for numbers - Logical Operators: Combine conditions with
&&,||, and! - File Tests: Extensive operators for checking file properties
- String Operators: Powerful manipulation with pattern matching
- Bitwise Operators: Low-level bit manipulation
- Precedence: Understand and use parentheses for clarity
Best Practices
- Use
[[ ... ]]instead of[ ... ]for more features and fewer surprises - Use
(( ... ))for arithmetic comparisons instead of-eq,-gt, etc. - Always quote variables in string comparisons:
[[ "$var" == "value" ]] - Use parentheses to make operator precedence clear
- Validate input before using in arithmetic operations
- Use
-zand-nfor empty string checks - Combine file tests with logical operators for robust file handling
Common Pitfalls
# Pitfall 1: Spaces matter in test commands [ $a = $b ] # Correct spacing [$a=$b] # Wrong - will cause error # Pitfall 2: Variable quoting [[ $var == "" ]] # Wrong - will fail if var contains spaces [[ "$var" == "" ]] # Correct # Pitfall 3: Integer vs string comparison if [[ $a > $b ]] # String comparison (wrong for numbers) if (( a > b )) # Integer comparison (correct) # Pitfall 4: Assignment vs comparison if [ $a = $b ] # Comparison (correct) if [ $a = $b ] # Assignment - no, this is also comparison in test # Assignment is just: a=$b # Pitfall 5: Missing then keyword if [ condition ] # Then must be on next line or with semicolon then commands fi # Or: if [ condition ]; then commands fi
Mastering Bash operators is essential for writing effective shell scripts. Practice combining different operators to create powerful conditional logic and data manipulations.