BASH Programming

The Bash Conditionals In-Depth Study

A condition is a test expression that either results in True or False. If it is True, the script will continue in one way. If it is False, the script will continue in an alternate way. A condition may be used to know, for example, if a file exists. Another condition may be to know if the number for a variable is less than another number for another variable. In fact, there are many conditions, and they have been categorized. The condition is coded in a special way. Conditions are used in if-constructs and loop constructs.

This article explains how conditions are coded and used in if-constructs. Conditions are used in loop-constructs in a similar way. In Bash, True is an exit status of 0, and False is an exit status of 1.

Article Content

if-Construct

if
This construct begins with the reserved word “if” and ends with the reserved word, “fi”, which is “if” written in the opposite manner. Consider the following code:

theVar=15
if [ $theVar -eq 15 ]; then
    echo I am studying Bash.
fi

The output is:

I am studying Bash.

The condition is “$theVar -eq 15”, which means the value of $theVar is equal to 15. The -eq symbol means, is equal to. The condition is enclosed in square brackets. There must be a space between [ and the condition, and there must also be a space between the condition and ], as shown above.

In fact, [ condition ] means test. It means test whether the condition is True or False. If it is True, then do what is in the body of the construct.

Note: The use of the reserved word “then” is preceded by a semicolon. The body of the if-construct here has only one command. It can have more than one command. All of which will be executed if the condition is True.

The only semicolon in the above code can be omitted if the word “then” is typed in the next line, as in the following code:

theVar=15
if [ $theVar -eq 15 ]
then
    echo I am studying Bash.
fi

In a condition in Bash, the operators and operands are arguments. So, $theVar, -eq, and 15 are arguments. If all the arguments are arithmetical, then the double parentheses can be used to delimit the condition, as the following code shows:

theVar=15
if (($theVar == 15)); then
    echo I am studying Bash.
fi

Here, == means, equal to.

else

So, if the condition is True, the body of the if-construct will be executed.

What if the condition is False? If the condition is False, the body will not be executed; but it is possible for another body to be executed as a result. This other body is introduced with the reserved word “else”.

The following code illustrates this:

theVar=17
if [ $theVar -eq 15 ]; then
    echo I am studying Bash.
else
    echo I am doing something else.
fi

The output is:

I am doing something else.

There are two bodies here: the if-body and the else-body. Since $theVar (17) is not equal to 15, the else-body is executed. Here, the reserved word, “fi” is at the end of the total construct. The “fi” word is always at the end of any if-construct, as the code samples below illustrate:

In the above code, one of two bodies is executed: if the condition is True, the if-body is executed. Else, the else-body is executed.

elif

“elif” means “else if”.

Is it possible to have more than two bodies in a larger if-construct, such that only one body would be executed? Yes, it is possible! To achieve this, use the reserved word “elif” at least once, in place of “else”. The following code illustrates this:

theVar=1500
if [ $theVar -eq 15 ]; then
    echo Number is small.
elif [ $theVar -eq 150 ]; then
    echo Number is medium.
elif [ $theVar -eq 1500 ]; then
     cho Number is large.
elif [ $theVar -eq 15000 ]; then
    echo Number is very large.
fi

The output is:

Number is large.

In this code, there are four bodies: the if-body and three elif-bodies. Each body has a condition. For the four bodies (including the if-body), the first one whose condition is True is executed. Evaluation begins from the top.

else, the Default Condition

The reader now knows how to execute one body from a set of different bodies.

What if no condition is True? Should there not be a default body to execute if no condition is True? Well, it is possible to have a default body execute if no condition is True. This body is coded at the end of a complete if-construct, and it is introduced by the reserved word, “else”.

The following code illustrates this, where theVar=15000:

theVar=150000
if [ $theVar -eq 15 ]; then
    echo Number is small.
elif [ $theVar -eq 150 ]; then
    echo Number is medium.
elif [ $theVar -eq 1500 ]; then
    echo Number is large.
elif [ $theVar -eq 15000 ]; then
    echo Number is very large.
else
    echo Number is extremely large.
fi

The output is:

Number is extremely large.

Note: That “else” does not have a condition, and it also does not use the reserved word, “then”.

Remember that each body can have more than one command. The above code is an example of the complete if-construct.

The Test Command

A substitute for the [ command is the test command. The following code illustrates this:

theVar=15
if test $theVar -eq 15; then
    echo I am studying Bash.
fi

The output is:

I am studying Bash.

Note that there is no opening or closing ] for the test command.

Simplified Case Command

The case command is like the simplified if-elif-else command.
However, here the variable has to match the second operand in the condition. The above if-elif-else command, with the default clause, is replaced by the following case command, but with theVar=1500:

theVar=1500
case  $theVar in
    (15)
        echo Number is small. ;;
    (150)
        echo Number is medium. ;;
    (1500)
        echo Number is large. ;;
    (15000)
        echo Number is very large. ;;
    (*)
        echo Number is extremely large. ;;
esac

The output is:

Number is large.

The case compound command begins with the reserved word “case” and ends with the reserved word “esac”, which is the backward spelling of “case”. In the previous code, there are two operands: the first operand, theVar, followed by the operator, -eq, and then the second operand, which is a number such as 15. Here, the first operand is typed only once, in the first line. This is followed by the reserved word, in. After the reserved word, in, the Enter key should be pressed for a new line.

Each clause begins with its second operand, and then it is followed by its body. A clause here, consists of its second operand, followed by its group of commands. In this script, each clause has only one command, but there can be more than one command. The last command of each clause should end with “;;”. A clause can also end with “;&”, or “;;&” as depicted in the following examples.

Note: The default clause has a second operand, which is *.* in this situation, matches anything.

select Command Simplified

The select command is a compound command. It works with a list (or array). When the select command is executed, the values of the list or array are displayed at the terminal. Each value is preceded by a number. The first value at the display is numbered as 1; the second value is numbered as 2; the third is numbered as 3; and so on. This display is a vertical menu.

At the bottom of the list, at the display (terminal), the special prompt, #? is shown, followed on its right, by a flashing cursor. This flashing cursor is waiting for the computer user to type any number from the (vertical) list and press Enter. When the user types a number, the corresponding value is selected. That value can now be sent as an argument to a function by the script. An example will be provided.

If the break command were the last command in the compound select command, then after the user enters the number, the script would continue to operate.

The syntax for the select command is:

select name [in list]
do
    [commands]
done

Wherein, “select”, “in”, “do”, and “done” are the reserved words. The “list” word is an array or a simple list. The “name” word refers to the item that would be selected in the list.

The reader should try the following code, entering any number of the list, when the special prompt appears:

animals=(dog bat rat pig cat)
select item in ${animals[@]}
do
    echo You selected "$item" whose number is $REPLY .
    break
done

The initial display should be:

1) dog
2) bat
3) rat
4) pig
5) cat
#?

If the reader (user) types in 2 and presses Enter, then the output (second display) would be:

You selected “bat” whose number is 2.

“$REPLY” is a predefined variable, which holds the number typed in by the user.

Note The use of the break command in the compound select command above.

Not Equal To and Logical Not Operators

Not Equal To Operators

There are two not-equal-to operators, which are “!=” and “ne”. They have different contexts of application. Please see below:

Basically, the not-equal-to operator returns True if its right operand (expression) is False.

A binary expression is one, which has one operand on either side of the operator. With the not-equal-to operators, there are two operands, one on either side.

The following code illustrates the use of the not-equal-to operator:

theVar=14
if  [ $theVar -ne 15 ]; then
    echo I am not studying Bash.
fi

The output is:

I am not studying Bash.

The logical Not Operator

The logical Not operator is “!”. If the right operand to “!” is False, then the result is True. If the right operand to “!” is True, then the result is False.

A unary expression is one, which has only one operand on either side of the operator. The operand can be on the left side or on the right side. With the logical Not operator, the operand is on the right. The following code illustrates the use of the logical Not operator:

if  [ ! -d "myDir" ]; then
    mkdir "myDir"
fi

If the directory “myDir” does not exist, then it will be created. The -d “myDir” means return True if the directory exists, or False if the directory does not exist. If False, then when preceded by “!”, the result for the condition would be True. The body of this construct is executed, only when the result of the condition is True.

Some Predefined Unary Conditional Expressions

In the following expressions, the word “file” should be replaced by the name of the file or the name of the directory. The expressions can be used as in the above condition.

-a file
Returns True if the file exists.

-b file
An example of a block file is an image file. This returns True if the file exists, and it is a block file.

-c file
Returns True if the file exists, and it is a text file.

-d file
Returns True if the file exists, and it is a directory.

-e file
Returns True if the file exists, and it does not matter if it is a text file or a block file.

-f file
Examples of regular files are: executable files, text files, and image files. This returns True if the file exists, and it is a regular file.

-r file
Returns True if the file exists, and it is readable.

-s file
Returns True if the file exists, and it has a size greater than zero.

-t fd
Returns True if the file descriptor “fd” is open and refers to a terminal.

-w file
Returns True if file exists, and it is writable.

-x file
Returns True if the file exists, and it is executable.

-N file
Returns True if the file exists, and it has been modified since it was last read.

The following example checks if the file named filenam.txt, exists:

if  [ -e "filenam.txt" ]; then
    echo File exist.
else
    echo File does not exist!
fi

Operators

The Equal to Operators
The equal to operators are “-eq” and “==”. The “-eq” is used when both operands are numbers, while “==” is used when both operands are strings. Example:

if [ 25 -eq 25 ]; then
    echo Numbers are equal.
fi

if [ "one" == "one" ]; then
    echo Strings are equal.
Fi

The output is:

Numbers are equal.
Strings are equal.

The Not Equal To Operators

The not-equal-to operators are “-ne” and “!=”. The “-ne” is used when both operands are numbers, while “!=” is used when both operands are strings. Example:

if [ 24 -ne 26 ]; then
    echo Numbers are not equal.
fi

if [ "one" != "something" ]; then
    echo Strings are not equal.
fi

The output is:

Numbers are not equal.
Strings are not equal.

That is, if 24 is not equal to 26, then the corresponding body is executed. Otherwise, it is not executed. And if “one” is not equal to “something”, then the corresponding body is also executed. Otherwise, it is not executed.

The Less Than Operators

The less-than operators are “-lt” and “<”. The “-lt” is used when both operands are numbers, while “<” is used when both operands are strings. Example:

if [ 13 -lt 17 ]; then
    echo First operand is less than second operand.
fi

if [[ "abcd" < "bcde" ]]; then
    echo First operand is less than second operand.
fi

The output is:

First operand is less than second operand.
First operand is less than second operand.

Note: For the strings, the [[ arguments ]] condition has been used. The delimiting spaces are still respected. Also, when comparing ASCII strings, digits come before lowercase letters, which in turn come before uppercase letters.

The Less Than or Equal-To Operator

The less-than-or-equal-to operator is “-le”. As of now, the less-than-or-equal-to operator exists only for numbers. It is still to be designed for strings. Number example:

if [ 18 -le 17 ]; then
    echo First operand is less than or equal to second operand.
fi

There is no output; since 18 is greater than 17.

The Greater Than Operators

The greater-than operators are “-gt” and “>”. The “-gt” is used when both operands are numbers, while “>” is used when both operands are strings. Example:

if [ 17 -gt 13 ]; then
    echo First operand is greater than second operand.
fi

if [[ "bcde" > "abcd" ]]; then
    echo First operand is greater than second operand.
fi

The output is:

First operand is greater than second operand.
First operand is greater than second operand.

Note: For the strings, the [[ arguments ]] condition has been used. The delimiting spaces are still present. Also, when comparing ASCII strings, digits come before lowercase letters, which in turn come before uppercase letters.

The Greater Than or Equal To Operator

The greater-than-or-equal-to operator is “-ge”. As of now, the greater-than-or-equal-to operator exists only for numbers. It is still to be designed for strings. Number example:

if [ 18 -ge 17 ]; then
    echo First operand is greater than or equal to second operand.
fi

The output is:

First operand is greater than or equal to second operand.

Truth Tables

All the above conditions have only one expression, which results in True or False.

Single Expression

The truth table for a single expression is:

false = false
true = true
Not false = true
Not true = false

Two Expressions or’ed

It is possible to have two expressions or’ed. The truth table for two expressions that are or’ed is:

false OR false = false
false OR true = true
true OR false = true
true OR true = true

Two Expressions and’ed

It is possible to have two expressions and’ed. The truth table for two expressions that are “and’ed” is:

false AND false = false
false AND true = false
true AND false = false
true AND true = true

The reader must memorize these truth tables. It can be extended to three expressions and more. Examples are below:

Logical OR Operator

The logical Or operator is “||” . The truth table for two expressions for the logical Or, copied from above, is:

false || false = false
false || true = true
true || false = true
true || true = true

Again, false refers to one expression, and true also refers to another expression. The following code produces the OR truth table:

theVar=15

if [[ ($theVar -eq 14 || $theVar -eq 14) ]]; then
    echo true.
else
    echo false
fi

if [[ ($theVar -eq 14 || $theVar -eq 15) ]]; then
    echo true
else
    echo false
fi

if [[ ($theVar -eq 15 || $theVar -eq 14) ]]; then
    echo true
else
    echo false
fi

if [[ ($theVar -eq 15 || $theVar -eq 15) ]]; then
    echo true
else
    echo false
fi

The output is:

false
true
true
true

Note: the use of the [[ command and the parentheses. Also note the delimiting spaces.

Logical AND Operator

The logical AND operator is “&&”. The truth table for two expressions for the logical And, copied from above, is:

false && false = false
false && true = false
true && false = false
true && true = true

Again, false refers to one expression, and true also refers to another expression. The following code produces the AND truth table:

theVar=15

if [[ ($theVar -eq 14 && theVar -eq 14) ]]; then
    echo true.
else
    echo false
fi

if [[ ($theVar -eq 14 && $theVar -eq 15) ]]; then
    echo true
else
    echo false
fi

if [[ ($theVar -eq 15 && $theVar -eq 14) ]]; then
    echo true
else
    echo false
fi

if [[ ($theVar -eq 15 && $theVar -eq 15) ]]; then
    echo true
else
    echo false
fi

The output is:

false
false
false
true

Note: The use of the [[ command and the parentheses. Also, note the delimiting spaces.

Conclusion

A condition is a command with arguments. The arguments are operands and operators. The arguments can make up a single expression, two expressions, or more expressions. If the overall condition results in True, the script moves in one direction. If the overall condition results in False, the script moves in the alternate direction. The conditions are used in if-constructs and loop-constructs. For any language, the programmer has to know how to code condition for that language.

About the author

Chrysanthus Forcha

Discoverer of mathematics Integration from First Principles and related series. Master’s Degree in Technical Education, specializing in Electronics and Computer Software. BSc Electronics. I also have knowledge and experience at the Master’s level in Computing and Telecommunications. Out of 20,000 writers, I was the 37th best writer at devarticles.com. I have been working in these fields for more than 10 years.