Shell Scripting Part 3: Decision Control Structures in Shell Scripts

Hi! We already covered the basics of shell scripting such as accepting inputs, process data through arithmetic operations and generating and displaying output in the previous parts of this tutorial (part 1 and part 2). In this part, we will go deeper to a more advanced topic in a programming language -- making decisions in a program, but this time we will do it using bash shell. Let's get started!

Introduction

Most of our programming languages today are able to make decisions based on conditions we set. A condition is an expression that evaluates to a Boolean value - true or false. Any programmer can make his program smart based on the decision and logic he puts into his program. The bash shell supports if and switch (case) decision statements.

If statement

If is a statement that allows the programmer to make a decision in the program based on conditions he specified. If the condition is met, the program will execute certain lines of code otherwise, the program will execute other tasks the programmer specified. The following is the supported syntax of the if statement in the bash shell.

General Syntax

Single decision:

if <condition>
then
    ### series of code goes here
fi

Double decision:

if <condition>
then
    ### series of code if the condition is satisfied
else
    ### series of code if the condition is not satisfied
fi

Multiple if condition:

if <condition1>
then
    ### series of code for condition1
elif <condition2>
then
    ### series of code for condition2
else
    ### series of code if the condition is not satisfied
fi

Single-bracket syntax

if [ condition ]
then
    ### series of code goes here
fi

Double-bracket syntax

if ((condition))
then
    ### series of code goes here
fi

The single bracket syntax is the oldest supported syntax in bash shell. It is used together with all conditional statements in Linux. Meanwhile, the double-parenthesis syntax is used for a number-based conditional statement to provide a familiar syntax to programmers. All types of if statements need a specified condition in order to execute a task.

Conditional Statements in Linux

Conditional statements are used together with a decision control statement. There are different types of conditional statements that you can use in the bash shell, the most common ones are: file-based, string-based and arithmetic-based conditions.

File-based condition

File-based conditions are unary expressions and often used to examine a status of a file. The following list shows the most commonly used file-based conditions in the bash shell.

Operator Description
-a file Returns true if file exists
-b file Returns true if file exists and is a block special file
-c file Returns true if file exists and is a character special file
-d file Returns true if file exists and is a directory
-e file Returns true if file exists
-r file Returns true if file exists and is readable
-s file Returns true if file exists and has a greater size that zero
-s file Returns true if file exists and has a greater size that zero
-w file Returns true if file exists and is writable
-x file Returns true if file exists and is executable
-N file Returns true if the file exists and has been modified since it was last read

Making a file-based decision

Let's have an example that will illustrate how to construct a file-based decision in a bash script. In this example, we will create a script that determines whether the file exists in the home directory.

#!/bin/bash

cd
ls
if [ -e sample.sh ]
then
    echo "file exists!"
else
    echo "file does not exist"
fi

Making a file-based decision

In this example, we ensured that the shell will return to home directory regardless of our current active directory using the cd command. Additionally, the ls command is used to show the list of files in the directory for us to verify the file really exists or not. As you can see, the script outputs text "file exists!" because the sample.sh is in the home directory.

Note: The shell compiler is very strict in terms of syntax especially with spaces. There should be a space between if and the open bracket and in between brackets and the condition.

Now let's improve our script by making our code more dynamic by allowing user to input a script name and determine the permissions of the given file.

#!/bin/bash

cd
ls -l
read -p "Enter a file name: " filename
if [ -e $filename ]
then
    echo "file exists!"
    if [ -r $filename ]
    then
         status="readable "
    fi
    if [ -w $filename ]
    then
         status=$status"writable "
    fi
    if [ -x $filename ]
    then
         status=$status"executable"
    fi
     echo "file permission: "$status
else
    echo "file does not exist"
fi

Making a dynamic file-based decision

String-based Condition

Making decisions based on a string user-input is also possible in the bash shell. The string-based condition returns a binary expression as a result meaning, it returns true if the specified condition is satisfied otherwise, it returns false. The following are the commonly-used string-based conditional operators:

Operator Description
== Returns true if the strings are equal
!= Returns true if the strings are not equal
-n Returns true if the string to be tested is not null
-z Returns true if the string to be tested is null

Let's create a sample script using string-based conditional statement. The script will allow the user to input two strings and assess whether one of the strings is null, both string are equal and not equal.

#!/bin/bash

read -p "First String: " str1
read -p "Second String: " str2
if [ -z "$str1" ]
then
    echo "The 1st string is null"
elif [ -z "$str2" ]
then
    echo "The 2nd string is null"
else
    if [ $str1 == $str2 ]
    then
         echo "The strings are equal"
    else
        echo "The strings are not equal"
    fi
fi

String-based Conditional statement

Arithmetic-based Condition

The shell provides several ways in declaring an arithmetic-based condition. First is by using mnemonics that can be used together with the old-style single-bracket syntax and the other one is using mathematics-friendly symbols that can be used together with the double parenthesis

Below is the list of available mnemonics for arithmetic-based conditional statements in shell:

Operator Usage/Description
-eq Equal
-ge Greater Than or Equal
-gt Greater Than
-le Less Than or Equal
-lt Less Than
-ne Not Equal

Let's create a script that accepts an integer from the user and determines whether the integer is a zero, negative, odd or an even number.

#!/bin/bash

read -p "Enter an integer: " int1
if [ $int1 -eq 0 ]
then
    echo "Zero"
elif [ $int1 -lt 0 ]
then
    echo "Negative"
else
    if [ $((int1%2)) -eq 0 ]
    then
        echo "Even"
    else
        echo "Odd"
    fi
fi

Arithmetic-based Conditional statement

Arithmetic operator for double-parenthesis syntax:

Operator Usage/Description
== Equal
>= Greater Than or Equal
> Greater Than
<= Less Than or Equal
< Less Than
!= Not Equal

Now, let's reconstruct our previous script and use double-parenthesis syntax:

#!/bin/bash

read -p "Enter an integer: " int1
if (( $int1 == 0 ))
then
    echo "Zero"
elif (( $int1 < 0 ))
then
    echo "Negative"
else
    if (( $((int1%2)) == 0 ))
    then
        echo "Even"
    else
        echo "Odd"
    fi
fi

Arithmetic based operator

Switch Statement

The switch statement is another kind of conditional statement in shell scripting. It allows a programmer to compare several values against a variable in an easier way compared to if conditional statement. The syntax for switch statement is:


case in
<pattern1>)
    ##series of code for pattern1
    ;;
<pattern2>)
    ##series of code for pattern2
    ;;
<patternN>)
    ##series of code for patternN
    ;;
*)
    ##default statements
esac

The pattern is the possible value of the variable. Each pattern is separated with a double semi-colon which serves as a break statement of the pattern. The switch statement is closed with an esac statement.

#!/bin/bash
clear
read -p "Integer1: " int1
read -p "Integer2: " int2
echo "======================"
printf "Menu: \n[a] Addition\n[b]Subtraction\n[c]Multiplication\n[d]Division\n"
echo "======================"
read -p "Your choice: " choice
res=0
case $choice in
a)
    res=$((int1+int2))
;;
b)
    res=$((int1-int2))
;;
c)
    res=$((int1*int2))
;;
d)
    res=$((int1/int2))
;;
*)
    echo "Invalid input"
esac
echo "The result is: " $res

Switch statement in linux

Conclusion

The bash shell provides many useful tools for programmers. Just like most of programming languages today, it is also capable of making conditional decisions that makes shell scripts more interactive and smart. We will feature repetitive control structure in the next series. 'Till next time.

References

The next Lesson: Repetition Control Structures

Share this page:

3 Comment(s)

Add comment

Comments

From: Jose

Thank you for the tutorial.

The following line is duplicated:

-s file

Returns true if file exists and has a greater size that zero

From: Tony

Great tutorial! Please keep them coming.

From: Tony

Awesome!  More of this, please!