
Conditional Statements
Imagine you're a traffic controller at a busy intersection. When the light is green, you let cars drive through; when it's yellow, you prepare for a stop; and when it's red, you halt all traffic. This is exactly how conditional statements work in Bash scripts! They allow your scripts to make decisions and take different actions based on specific conditions - just like you would in everyday life.
Conditionals are the decision-makers of your scripts, evaluating whether something is true or false, and then directing the script's flow accordingly. Think of them as the "if this, then that" logic we use naturally: if it's raining, take an umbrella; otherwise, leave it at home. By incorporating conditionals into your scripts, you transform them from rigid, one-path sequences into intelligent programs that can adapt to different situations.
Let's explore how these digital decision-makers can make your scripts smarter and more flexible!
Quick Reference: Conditional Statements
Statement | Description | Common Use |
---|---|---|
if [[ condition ]]; then ... fi |
Basic conditional statement | Executing code only when a condition is true |
if [[ condition ]]; then ... else ... fi |
Two-way conditional statement | Choosing between two alternative actions |
if [[ condition1 ]]; then ... elif [[ condition2 ]]; then ... else ... fi |
Multi-way conditional statement | Making choices among multiple alternatives |
[[ ... ]] |
Enhanced test command (Bash-specific) | Testing conditions with advanced features |
[ ... ] |
Standard test command (POSIX-compliant) | Testing conditions in portable scripts |
&& and || |
Logical AND and OR operators | Combining multiple conditions |
Basic Conditional Structures
When to Use Conditional Statements
- When your script needs to make decisions based on user input
- When you need to handle different cases or scenarios
- When you want to check if files or directories exist before using them
- When you need to validate input before processing it
- When you need to handle errors or unexpected conditions
Common Conditional Structures
Structure | What It Does | When to Use It |
---|---|---|
Basic if statement | Executes commands only if a condition is true | When you have a single condition to check |
if-else statement | Executes one set of commands if condition is true, another if false | When you need to handle both true and false cases |
if-elif-else statement | Checks multiple conditions in sequence | When you have multiple possible scenarios |
Nested if statements | Places if statements inside other if statements | When conditions depend on other conditions |
Practical Examples
# Basic if statement
number=5
if [[ $number -gt 3 ]]; then
echo "The number is greater than 3"
fi
# if-else statement
number=2
if [[ $number -gt 3 ]]; then
echo "The number is greater than 3"
else
echo "The number is not greater than 3"
fi
# if-elif-else statement
number=3
if [[ $number -gt 3 ]]; then
echo "The number is greater than 3"
elif [[ $number -eq 3 ]]; then
echo "The number is equal to 3"
else
echo "The number is less than 3"
fi
# Nested if statement
number=4
if [[ $number -gt 0 ]]; then
if [[ $number -lt 10 ]]; then
echo "The number is between 1 and 9"
else
echo "The number is 10 or greater"
fi
else
echo "The number is zero or negative"
fi
Test Commands: [[ ]] vs [ ]
When to Use Different Test Commands
- Use
[[ ]]
when writing scripts specifically for Bash - Use
[ ]
when writing scripts that need to run on multiple Unix-like systems - Use
[[ ]]
when you need pattern matching or advanced string operations - Use
[ ]
for maximum portability across different shells - Use
[[ ]]
when working with variables that might contain spaces or be empty
Comparison of Test Commands
Feature | [ ] (Single Brackets) |
[[ ]] (Double Brackets) |
---|---|---|
Shell Support | POSIX-compliant (works in all shells) | Bash, Ksh, Zsh only |
String Handling | Requires quoting variables | More forgiving with variable quoting |
Logical Operators | Uses -a (AND), -o (OR) |
Uses && (AND), || (OR) |
Pattern Matching | Not supported directly | Supports =~ for regex |
Word Splitting | Performs word splitting on variables | Prevents word splitting on variables |
Practical Examples
# String comparison with [ ]
VAR="hello"
if [ "$VAR" = "hello" ]; then
echo "Matched with single brackets"
fi
# String comparison with [[ ]]
VAR="hello"
if [[ $VAR == "hello" ]]; then
echo "Matched with double brackets"
fi
# Logical operators with [ ]
if [ "$num" -gt 5 -a "$num" -lt 10 ]; then
echo "Number is between 6 and 9 (using single brackets)"
fi
# Logical operators with [[ ]]
if [[ $num -gt 5 && $num -lt 10 ]]; then
echo "Number is between 6 and 9 (using double brackets)"
fi
# Pattern matching (only works with [[ ]])
filename="document.txt"
if [[ $filename == *.txt ]]; then
echo "Text file detected"
fi
# Regex matching (only works with [[ ]])
VAR="hello123"
if [[ $VAR =~ ^hello[0-9]+$ ]]; then
echo "Matches regex pattern"
fi
Comparison Operators
When to Use Different Comparison Types
- Use string comparisons when working with text
- Use numeric comparisons when working with numbers
- Use file test operators when checking file properties
- Use string pattern matching when searching for specific patterns
- Use logical operators to combine multiple conditions
Common Comparison Operators
Comparison Type | Operator | Description |
---|---|---|
String Comparison | == |
Equal to |
!= |
Not equal to | |
=~ |
Matches regular expression (only with [[ ]] ) |
|
Numeric Comparison | -eq |
Equal to |
-ne |
Not equal to | |
-gt |
Greater than | |
-lt |
Less than | |
-ge |
Greater than or equal to | |
-le |
Less than or equal to | |
String Tests | -z |
String is empty |
-n |
String is not empty | |
File Tests | -f |
File exists and is a regular file |
-d |
File exists and is a directory | |
-r |
File exists and is readable | |
Logical Operators | && |
Logical AND |
|| |
Logical OR |
Practical Examples
# String comparison
name="Alice"
if [[ $name == "Alice" ]]; then
echo "Hello Alice!"
fi
# Numeric comparison
age=25
if [[ $age -ge 18 ]]; then
echo "You are an adult"
fi
# String emptiness test
input=""
if [[ -z $input ]]; then
echo "No input provided"
fi
# File test
if [[ -f "config.txt" ]]; then
echo "Config file exists, reading settings..."
cat config.txt
else
echo "Creating default config file..."
echo "default_setting=true" > config.txt
fi
# Combining conditions with logical operators
temperature=72
humidity=65
if [[ $temperature -gt 70 && $humidity -lt 80 ]]; then
echo "Weather is warm and comfortable"
fi
# String pattern matching
filename="document.pdf"
if [[ $filename == *.pdf ]]; then
echo "PDF document detected"
elif [[ $filename == *.txt ]]; then
echo "Text file detected"
else
echo "Unknown file type"
fi
Advanced Conditional Techniques
When to Use Advanced Techniques
- When you need to handle complex decision trees
- When you want to create more concise and readable code
- When checking multiple related conditions
- When you need to validate input against patterns
- When your script needs to adapt to different environments
Advanced Conditional Techniques
Technique | What It Does | When to Use It |
---|---|---|
Short-circuit evaluation | Uses && and || to execute commands conditionally |
For simple conditional execution without full if statements |
Case statements | Matches a value against multiple patterns | When checking a single variable against many possible values |
Command success testing | Uses a command's exit status in a condition | When your condition depends on a command's success |
Parameter expansion with defaults | Sets default values for variables that are unset or empty | For handling optional parameters gracefully |
Practical Examples
# Short-circuit evaluation
[[ -f config.txt ]] && echo "Config file exists"
[[ -f config.txt ]] || echo "Config file missing"
# Command success as a condition
if grep -q "error" log.txt; then
echo "Errors found in log file"
fi
# Testing command-line arguments
if [[ $# -lt 2 ]]; then
echo "Error: Not enough arguments"
echo "Usage: $0 filename count"
exit 1
fi
# Parameter expansion with default
name=${1:-"Guest"} # Use "Guest" if $1 is not provided
echo "Hello, $name!"
# Complex condition with multiple checks
file=$1
if [[ -f $file && -r $file && $file == *.txt ]]; then
echo "Reading text file: $file"
cat "$file"
else
echo "File $file is not a readable text file"
fi
Learning Aids
Tips for Success
- Always quote variables - Even with
[[ ]]
, quoting variables is a good habit that prevents issues with spaces and special characters - Use
[[ ]]
when possible - Double brackets provide more features and safer behavior in most cases - Indent your code - Proper indentation makes conditional blocks much easier to read and debug
- Test your conditions - Use
echo
to print the result of complex conditions to verify they work as expected - Use descriptive variable names - Names like
is_valid
orfile_count
make your conditionals self-documenting - Break complex conditions into parts - Assign parts of complex conditions to variables with meaningful names
- Use functions for repeated tests - If you use the same condition in multiple places, create a function for it
- Add comments - Explain the purpose of complex conditionals, especially for edge cases
Common Mistakes to Avoid
- Forgetting spaces inside brackets -
[[$var == "value"]]
is incorrect; use[[ $var == "value" ]]
- Using
=
instead of==
-=
is for assignment,==
is for comparison - Mixing string and numeric comparisons -
==
is for strings,-eq
is for numbers - Omitting then/fi keywords - Every
if
needs a matchingthen
andfi
- Not escaping special characters in
[ ]
- Characters like<
need escaping in single brackets - Using
[[
without]]
- Always ensure your brackets are balanced - Assuming all variables exist - Check if a variable exists before using it in conditions
- Using Bash-specific features in
/bin/sh
scripts - If your shebang is#!/bin/sh
, avoid[[ ]]
Best Practices
- Use meaningful exit codes - Return 0 for success and specific non-zero values for different errors
- Check user input thoroughly - Validate all user input before using it in your scripts
- Handle edge cases - Consider what happens if files don't exist or inputs are unexpected
- Provide helpful error messages - When conditions fail, give users clear information about what went wrong
- Use early returns - Exit from scripts early when prerequisites aren't met
- Be consistent with your style - Choose either
[[ ]]
or[ ]
and stick with it throughout your script - Test conditions separately - For complex conditions, test each part individually first
- Default to safe behavior - When in doubt, make your script fail safely rather than proceed with uncertainties
Summary
Conditional statements are the decision-makers in your Bash scripts, allowing you to create dynamic and responsive code. By using if, else, and elif statements with various comparison operators, you can create scripts that adapt to different inputs, handle errors gracefully, and make intelligent choices based on the environment.
Whether you're writing simple scripts or complex programs, mastering conditionals is essential for effective Bash scripting. Understanding when to use different test commands, comparison operators, and conditional structures will help you write more robust and maintainable scripts that can handle the complexities of real-world scenarios.