WCC logo

CIS120Linux Fundementals

Conditional Statements (if, else, elseif)

Conditional Expressions

Conditional expressions in Linux are used in shell scripting to evaluate conditions and control the flow of execution. They are typically used in conditional statements (if, else, elseif), while loops, and other control structures to make decisions based on comparisons, file attributes, or logical operations.

In Linux shell scripting, [ ] (or test) and [[ ]] are used to evaluate conditional expressions, but [[ ]] provides additional functionality and is preferred in modern Bash scripting. Here's a breakdown of the differences:

Basic Differences

Feature [ ] (Single Brackets) [[ ]] (Double Brackets)
Shell Built-in Yes (but also a standalone test command) Yes (Bash/Ksh specific)
Operators Supports basic test conditions Supports additional operators
String Comparisons Requires escaping > and < No escaping needed
Logical Operators Uses -a (AND), -o (OR) Uses && (AND), `
Pattern Matching No (except with expr) Supports =~ for regex
Variable Expansion May cause word splitting and globbing Prevents word splitting

Examples

Example 1: String Comparison

Using [ ] (requires quoting variables to avoid errors if empty):

VAR="hello"
if [ "$VAR" == "hello" ]; then
    echo "Matched"
fi

Using [[ ]] generally safer, and quoting is not required in most cases. However, quotes are needed if the variable may be empty or contain spaces, especially when using string comparisons or pattern matching. NOTE: An empty variable won't cause a syntax error, while with [ ... ], it will if quotes are missing. While quoting is always a good practice, [[ ... ]] is more forgiving.

VAR="hello"
if [[ $VAR == "hello" ]]; then
    echo "Matched"
fi

Example 2: Numeric Comparison

Both work the same for numbers:

NUM=10
if [ "$NUM" -gt 5 ]; then
    echo "Greater than 5"
fi
NUM=10
if [[ $NUM -gt 5 ]]; then
    echo "Greater than 5"
fi

Example 3: File Existence Check

Both work the same:

if [ -f "/etc/passwd" ]; then
    echo "File exists"
fi
if [[ -f "/etc/passwd" ]]; then
    echo "File exists"
fi

Example 4: Logical AND/OR

[ ] requires -a and -o, which can be problematic:

if [ -f "/etc/passwd" -a -r "/etc/passwd" ]; then
    echo "File exists and is readable"
fi

[[ ]] allows && and ||, making it clearer:

if [[ -f "/etc/passwd" && -r "/etc/passwd" ]]; then
    echo "File exists and is readable"
fi

Example 5: String Comparison (<, >)

With [ ], < and > must be escaped:

if [ "apple" \< "banana" ]; then
    echo "Apple comes before banana"
fi

With [[ ]], no escaping is needed:

if [[ "apple" < "banana" ]]; then
    echo "Apple comes before banana"
fi

Example 6: Regex Matching (Only with [[ ]])

[[ ]] supports regex with =~:

VAR="hello123"
if [[ $VAR =~ ^hello[[0-9]+$ ]]; then
    echo "Matches regex pattern"
fi

This would not work with [ ] since it lacks regex support.

Summing Up [ ] and [[ ]]

The [ ] conditional expression is a Bash/Ksh-specific feature and is not available in POSIX-compliant shells like /bin/sh. This means that scripts intended to run in environments where only POSIX sh is available, such as older Unix systems, minimal Linux distributions, or embedded systems, may not support [[ ]]. Instead, they require the use of [ ] (or test). Additionally, if a script explicitly specifies #!/bin/sh as its interpreter, it may not support [[ ]], depending on the system’s shell implementation. To ensure portability, scripts intended for generic POSIX environments should avoid [[ ]] and use [ ] instead.

If, Else and ElseIf Statments

In Linux shell scripting, if, else, and elif (else if) statements are used to create conditional logic, allowing scripts to execute different commands based on specific conditions. The if statement evaluates a condition, and if it is true, the corresponding block of code executes. If the condition is false, an else statement can provide an alternative execution path. The elif statement allows for multiple conditions to be checked sequentially, executing the first matching condition and skipping the rest. These statements help control the flow of execution by making decisions dynamically, which is essential for automation, error handling, and interactive scripts.

Let's take a look at how we use if, else and else if statements.

Basic if Statement

A basic if statement in Bash follows this syntax:

if [[ condition ]]; then
    # Commands to execute if condition is true
fi

In this example, the script checks if the variable number is greater than 3 and prints a message if the condition is true.

#!/bin/bash

number=5

if [[ $number -gt 3 ]]; then
    echo "The number is greater than 3"
fi

if-else Statement

An if-else statement allows you to execute different commands based on whether the condition is true or false.

if [[ condition ]]; then
    # Commands to execute if condition is true
else
    # Commands to execute if condition is false
fi

In this example, the script prints a different message based on whether the number is greater than 3.

#!/bin/bash

number=2

if [[ $number -gt 3 ]]; then
    echo "The number is greater than 3"
else
    echo "The number is not greater than 3"
fi

Multiple if-else Statements (elif)

You can use multiple if-else statements to test several conditions.

if [[ condition1 ]]; then
    # Commands to execute if condition1 is true
elif [[ condition2 ]]; then
    # Commands to execute if condition2 is true
else
    # Commands to execute if neither condition1 nor condition2 is true
fi

In this example, the script checks multiple conditions and prints the appropriate message based on the value of number.

#!/bin/bash

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-else Statements

Nested if-else statements are if-else statements within another if-else statement.

In this example, the script first checks if the number is greater than 0. If true, it then checks if the number is less than 10 and prints the appropriate message based on the nested conditions.

#!/bin/bash

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

Comparisons in Bash

In Bash, you can use various comparison operators to test conditions.

Equality (==):

if [[ "$str1" == "$str2" ]]; then
    echo "Strings are equal"
fi

Regex Match (=~):

if [[ "$str" =~ ^[0-9]+$ ]]; then
    echo "String contains only digits"
fi

Inequality (!=):

if [[ "$str1" != "$str2" ]]; then
    echo "Strings are not equal"
fi

Numeric Comparisons:

Greater than (-gt):

if [[ $num1 -gt $num2 ]]; then
    echo "$num1 is greater than $num2"
fi

Less than (-lt):

if [[ $num1 -lt $num2 ]]; then
    echo "$num1 is less than $num2"
fi

Greater than or equal to (-ge):

if [[ $num1 -ge $num2 ]]; then
    echo "$num1 is greater than or equal to $num2"
fi

Less than or equal to (-le):

if [[ $num1 -le $num2 ]]; then
    echo "$num1 is less than or equal to $num2"
fi

Equal to (-eq):

if [[ $num1 -eq $num2 ]]; then
    echo "$num1 is equal to $num2"
fi

Not equal to (-ne):

if [[ $num1 -ne $num2 ]]; then
    echo "$num1 is not equal to $num2"
fi

Checks if a file exits using (-f). If so then outputs the contents, if not then says "No file found".

if [[ -f file.txt ]]; then
    echo "File contents:"
    cat file.txt
else
    echo "No file found."
fi

Logical Operators

You can also use logical operators to combine multiple conditions.

AND (&&):

if [[ $num -gt 0 ]] && [[ $num -lt 10 ]]; then
    echo "The number is between 1 and 9"
fi

OR (||):

if [[ $num -eq 0 ]] || [[ $num -eq 10 ]]; then
    echo "The number is 0 or 10"
fi

String Comparisons

String comparisons in Bash can also be performed using various operators:

Check if a string is empty (-z):

if [[ -z "$str" ]]; then
    echo "String is empty"
fi

Check if a string is not empty (-n):

if [[ -n "$str" ]]; then
    echo "String is not empty"
fi

Check if a string starts with a specific substring:

if [[ "$str" == prefix* ]]; then
    echo "String starts with 'prefix'"
fi

Comparison Operators Table

Comparison Operator Example Description
Equality == [[ "$str1" == "$str2" ]] Strings are equal
Regex Match =~ [[ "$str" =~ ^[0-9]+$ ]] String matches regex
Inequality != [[ "$str1" != "$str2" ]] Strings are not equal
Numeric Greater -gt [[ $num1 -gt $num2 ]] num1 is greater than num2
Numeric Less -lt [[ $num1 -lt $num2 ]] num1 is less than num2
Numeric Greater or Equal -ge [[ $num1 -ge $num2 ]] num1 is greater than or equal to num2
Numeric Less or Equal -le [[ $num1 -le $num2 ]] num1 is less than or equal to num2
Numeric Equal -eq [[ $num1 -eq $num2 ]] num1 is equal to num2
Numeric Not Equal -ne [[ $num1 -ne $num2 ]] num1 is not equal to num2
String Empty -z [[ -z "$str" ]] String is empty
String Not Empty -n [[ -n "$str" ]] String is not empty
String Starts With == prefix* [[ "$str" == prefix* ]] String starts with 'prefix'
Checks if file exits -f [[ -f file.txt ]] Checks if file.txt exits
Logical AND && [[ $num -gt 0 ]] && [[ $num -lt 10 ]] Both conditions are true
Logical OR || [[ $num -gt 10 ]] || [[ $num -lt 5 ]] Only one condition needs to be true for this condtion to evaluate as true

Summary

Bash provides powerful constructs to handle conditional execution using if, if-else, and nested if-else statements. Various comparison operators like ==, =~, !=, -gt, -lt, and logical operators && and || help in forming complex conditions. Understanding these constructs and operators allows you to write more efficient and readable Bash scripts.