Basics of the IF statement

If staments are used to make decisions in Bash scripts. They are used to determine what happens if a certain condition is true or not. If statements allows to make more complex scripts.

The basic if statement starts with a word if and it's followed by the conditional statement. In most cases this statement is a test, that is encapsulated in square brackets [].
The following lines describe what happens if the test is true (word then). If test returns false, nothing is performed.
Finally, the if stament ends on the word fi (happens to be if backwards)

The basic syntax:

#!/bin/bash
if <condition>
then
  <commands>
fi

The test syntax:

#!/bin/bash
if [ <test-condition> ]
then
  <commands>
fi

# is the same as

if test <test-condition>
then
  <commands>
fi

Note that in the if statement above commands were indented. This is not necessary in Bash, just a good good practice to keep your code clean.


Tests

The syntax: [ condition-to-test-for ] or test <condition-to-test-for>

As mentioned earlier, conditional expressions were also known as tests. Why?
Those square brackets [] are actually a reference to the Bash's builtin command test.
Command's manual describes multiple operators that can be used in multiple different test situations. For example, operators can be used to compare is the number greater than another, are the string the same or is the file empty.
The most common ones are shown on the following chapters. You can run command help test in your terminal to list these.


Relational operators

Relational operators also known as comparasition operators are used to compare two variables or quantities. Return True of False values. Note that values must be integer numbers, but numbers can be defined as a string. There are different set of operators for strings!

  • -eq = is equal to (integers)
  • = = is equal to (strings)
  • -ne = not equal to
  • -lt = is less than
  • -le = is less than or equal to
  • -gt = is greater than
  • -ge = is greater than or equal to
  • < = is smaller than with
  • <= = is less than equal to
  • > = is greater than
  • >= = is greater than or equal to

Note that conditional expressions should be encapsulated with square brackets with spaces.

#!/bin/bash

if [ 10 -lt 100 ]
then
  echo "smaller than 100"
fi

if [ 99 -ne 999 ]
then
  echo "numbers arent equal"
fi

File operators

Syntax: operator FILE

  • -d = True if the file is a directory
  • -e = True if the file exists
  • -f = True if the file exists and is a regular file (not a directory or device)
  • -r = True if the file is readable by the user
  • -s = True if the file exists and is not empty
  • -w = True if the file is writable by the user
  • -x = True if the file is executable by the user

String operators

  • -z STRING = True if the string is empty (null)
  • -n STRING = True if the string is not empty (not null)
  • STRING = True if the string is not empty
  • STRING1 = STRING2 = True if the strings are equal
  • STRING != STRING2 = True if the strings are not equal

If Else

In some cases there might be different set of actions to perform depending if the conditon is ether a true or false.
Else statement can be used to describe what will happen if the if statement's condition is false.

The basic syntax:

#!/bin/bash

if [ <test> ]
then
  <commands>
else
  <other commands>
fi

Lets take a simple example:

#!/bin/bash

number=10

if [ ${number} -gt 17 ] #test returns false
then
  echo "20 is bigger than 17" #not executed
else
  echo "Number is lower than 17" #executed
fi

#-----------------------------------------------------

#AND example

age=55

if [ ${age} -gt 17 ] && [ ${age} -le 60]
then
  echo "you are not young or too old"
else
  echo "see you later alligator"

If Elif Else

Sometimes simple if else statement is not enough. You might have multiple conditions that lead to different outcomes.
The elif statement allows to define multiple conditions on the "same level". The word elif is a contraction for else if.
There is no limit how many elif statements you can define and else statement is optional.
If the normal if statement condition is false, the first elif statement condition will be evaluated and so on, else block will be executed if all defined if and elif statement conditions are false.

The basic syntax:

#!/bin/bash

if [ <test> ]
then
  <commands>
elif [ <test> ]
then
  <different commands>
else
  <other commands>
fi

A simple example:

#!/bin/bash

food=potato

if [ ${food} = "potato" ]
then
  echo "You seem to like potatos!"
elif [ $food = "carrot" ]
then
  echo "You seem to like carrots!"
else
  echo "Can you eat anything?"
fi

Nested if statements

The were a comment on the earlier section that identing is not necessary, just a good coding practice. Well now comes a example case were it's very usefull: Nested statements.
Many times there is a need to have other statements inside of another if statement. In other words, you might have other conditions based on the earlier condition.

#!/bin/bash

if [ <test> ]
then
  <commands>

  if [ <nested test> ]
  then
    <commands>
  fi
fi

Lets take example where we must check if the number is smaller than 100 and also if it's an even number:

#!/bin/bash

number=98

if [ ${number} -lt 100 ] 
then
  echo Number is a under 100

  if (( $NUMBER % 2 == 0 )) 
  then
    echo Number is also an even number.
  fi
fi

Boolean operators

Many times a multiple conditions must be met before the action can be performed. Boolean operators can be accomodate those.

  • || = or
  • && = and

Perhaps you need to perform something different if the name is Arttu or Anna.
Or maybe youy want to perform an operation if the file is readable and if a size is greater than zero.

#!/bin/bash

#OR example

name="Arttu"

if [ ${name} = "Arttu" ] || [ ${name} = "Anna" ]
then
  ls -la / #list a active directory using a long listing format and show hidden files
else
  ls / # list a root directory
fi

#---------------------------------------

#AND example

file="/etc/hosts"

if [ -r ${file} ] && [ -s ${file} ]
then
  echo This file is useful.
fi

Case statement

You should now know how to make decisions and vary the flow in your scripts with a if statement, but there is also a quite rare one that is usefull in some cases: case
The case statemtn is used to shoose a set of commands to execute depending on a string matching a given pattern.
The main purpose is to decrease expression counts in you shell scripts. So, if you find yourself to multiple if staments to compare the same variable, a case statement might be a good practice in that place.

The basic syntax:

#!/bin/bash

case <variable> in # define a case statement
  <pattern1>)
    <commands>
    ;;
  <pattern2>)
    <commands>
    ;;
esac

To create a case statement, start with a word case and follow it with an expression and end the line with a word in.
Next, define a pattern or a value what you want to compare against the variable. Note that you can use OR | character to add other possibility (for example capital letters and lower letters) in a pattern. Remember to end the line with a closing paranthesis ). If the defined pattern matches the variable, the following commands will be executed.
The command block end to two semicolons ;; and the script execution will continue after the case statement. The case statement is ended with a word esac, that is a "case" spelled backwards.

Let use the earlier example as a base and modify it to use case statement:

#!/bin/bash

food=potato

if [ ${food} = "potato" ]
then
  echo "You seem to like potatos!"
elif [ ${food} = "carrot" ]
then
  echo "You seem to like carrots!"
else
  echo "Can you eat anything?"
fi


#--------- CASE STATEMENT ----------------

read -p "what food do you like?: " FOOD

case ${FOOD} in
  potato)
    echo "you like potatoes!"
    ;;
  tomato)
    echo "you like tomatoes"
    ;;
  *)
    echo "do you like anything?"
    ;;
esac

In a example above, a user defined variable was used. Of course you can use case statement for example with a command line arguments.


case $1 in
  potato|POTATO)
    echo "you like potatoes!"
    ;;
  tomato|TOMATO)
    echo "you like tomatoes"
    ;;
  *)
    echo "do you like anything?"
    ;;
esac

#example execution: ./example.sh potato
#output: potato