Terminus
Bash If Statement

Bash If Statement

The short answer

In Bash, the [.inline-code] if[.inline-code]  statement is a control structure that allows developers to execute one or more instructions based on the evaluation of a command or an expression called a condition.

If the condition evaluates to [.inline-code] true[.inline-code]  (i.e. the exit status equals zero), then the subsequent instructions are executed.

The syntax of the [.inline-code] if[.inline-code]  statement is as follows:

if condition; then
  instructions
fi

Where:

  • [.inline-code] if[.inline-code]  starts the conditional statement.
  • [.inline-code] condition[.inline-code]  is the expression that will be evaluated.
  • [.inline-code] then[.inline-code]  specifies the set of instructions to execute if the condition is true.
  • [.inline-code] fi[.inline-code]  ends the conditional statement.

For example, let's consider the following script, where the [.inline-code] echo[.inline-code]  command will only be executed if the exit status of the [.inline-code] grep[.inline-code]  command is [.inline-code] 0[.inline-code] :

#!/bin/bash

if grep -q error access.log; then
  echo "log contains errors"
fi

[#compare-values] Comparing values [#compare-values]

In order to compare two values together within an [.inline-code] if[.inline-code]  statement, you need to enclose the comparison expression within square brackets [.inline-code] [[.inline-code]  as follows:

if [ expression ]; then
  instructions
fi

Where:

  • [.inline-code] expression[.inline-code]  is a logical expression composed of variables, values, and comparison operators.

Note that this syntax is in fact an alias for the built-in [.inline-code] test[.inline-code]  command.

[#compare-numbers] Comparing numbers [#compare-numbers]

Numeric comparisons are done using the following operators:

  • [.inline-code] -eq[.inline-code] : equal to
  • [.inline-code] -ne[.inline-code] : not equal to
  • [.inline-code] -lt[.inline-code] : less than
  • [.inline-code] -le[.inline-code] : less than or equal to
  • [.inline-code] -gt[.inline-code] : greater than
  • [.inline-code] -ge[.inline-code] : greater than or equal to

For example, let's consider this script that makes the user guess a number:

 #!/bin/bash

number=5

while true;
do
  read -p "Guess the number: " input

  if [ $input -lt $number ]; then
    echo "Too low..."
    continue
  fi

  if [ $input -gt $number ]; then
    echo "Too high..."
    continue
  fi

  if [ $input -eq $number ]; then
    echo "Good guess!"
    break
  fi
done

[#compare-strings] Comparing strings [#compare-strings]

String comparisons are done using the following operators:

  • [.inline-code] =[.inline-code] : equal to
  • [.inline-code] !=[.inline-code] : not equal to 
  • [.inline-code] <[.inline-code] : less than
  • [.inline-code] >[.inline-code] : greater than

And the following flags:

  • [.inline-code] -z[.inline-code] : string is empty
  • [.inline-code] -n[.inline-code] : string is not empty

Note that when using flags, you can use the NOT [.inline-code] ![.inline-code]  operator to negate the expression.

For example, let’s consider this script that makes the user guess a word:

#!/bin/bash

word="hello"

echo "Guess the word (type 'quit' to exit)."

while :
do
  read -p "> " input

  if [ ! -n $input ]; then
    echo "Error: invalid input"
    continue
  fi

  if [ $input == "quit" ]; then
    echo "Goodbye!"
    break
  fi

  if [ $input != $word ]; then
    echo "Try again..."
    continue
  fi

  if [ $input == $word ]; then
    echo "Congratulations!"
    break
  fi
done

[#combine-conditions] Combining conditions [#combine-conditions]

The logical [.inline-code] &&[.inline-code]  (AND) and [.inline-code] ||[.inline-code]  (OR) operators allow you to combine two or more conditions into a single expression.

[#the-logical-and] The logical AND [#the-logical-and]

When using the AND operator, all conditions must evaluate to true for the subsequent instructions to be executed:

if [ condition ] && [ condition ]; then
  # instructions
fi

[#the-logical-or] The logical OR [#the-logical-or]

When using the OR operator, only one of the conditions must evaluate to true for the subsequent instructions to be executed:

if [ condition ] || [ condition ]; then
  # instructions
fi

[#evaluate-complex-conditions] Evaluating complex conditions [#evaluate-complex-conditions]

Unlike the single square brackets [.inline-code] [[.inline-code] , the double square brackets [.inline-code] [[[.inline-code]  provide a more advanced processing and evaluation of conditional expressions.

It retrieves the specified expression as a single string instead of separate arguments, and performs its own expansions.

if [[ expression ]]; then
  # instructions
fi

[#match-patterns] Matching simple and regex patterns [#match-patterns]

In addition, the double square brackets allow you to match simple and advanced patterns using the [.inline-code] =~[.inline-code]  operator.

Simple matchers include:

  • [.inline-code] [<chars>][.inline-code] : a specific set of characters
  • [.inline-code] ?[.inline-code] : a single character
  • [.inline-code] *[.inline-code] : any string/substring

Note that these matchers need to be placed outside of quotes as they will otherwise lose their meaning and be treated as regular characters.

For example, let’s consider this script that checks whether the file passed as argument of the script is a JavaScript or JSON file:

#!/bin/bash

if [[ "$1" =~ \.(js|json)$ ]]; then
    echo "Valid JS or JSON file"
fi

[#evaluate-arithmetic-expressions] Evaluating arithmetic expressions [#evaluate-arithmetic-expressions]

To easily perform basic arithmetic operations within an [.inline-code] if[.inline-code]  statement using mathematical operators, such as [.inline-code] +[.inline-code] , [.inline-code] -[.inline-code] , [.inline-code] *[.inline-code] , etc, and comparison operators, such as [.inline-code] >[.inline-code] , [.inline-code] <=[.inline-code] , [.inline-code] ==[.inline-code] , etc, you can use the double parentheses [.inline-code] (([.inline-code]  instead of the square brackets [.inline-code] [[[.inline-code]  as follows:

if (( expression )); then
  # instructions
fi

For example, [text]:

#!/bin/bash

number=1
i=2

if (( $number <= 2 )); then
  echo "not prime"
  exit 1
fi

while [ $i -lt $number ];
do
  if (( $number % $i == 0 )); then
    echo "not prime"
    exit 1
  fi
  ((i++))
done

echo "prime"

[#test-files-and-directories] Testing files and directories [#test-files-and-directories]

[#test-the-existence] Testing the existence [#test-the-existence]

To test the existence and type of files or directories you can respectively use the [.inline-code] -f[.inline-code]  and [.inline-code] -d[.inline-code]  flags.

For example:

if [ -f ./script.sh ]; then
  # instructions
fi
if [ -d /home/johndoe ]; then
  # instructions
fi

[#the-permissions] Testing permissions [#the-permissions]

To test whether a file or directory has read, write, or execute permission, you can respectively use the [.inline-code] -r[.inline-code] , [.inline-code] -w[.inline-code] , and [.inline-code] -x[.inline-code] flags.

if [[ ! -x ./my_script.sh ]]; then
    chmod +x my_script.sh
fi