Docs  >   Bash Handbook   >   Conditional-statements

Top

Conditional statements

Like in other languages, Bash conditionals let us decide to perform an action or not. The result is determined by evaluating an expression, which should be enclosed in [[ ]].

Conditional expression may contain && and || operators, which are AND and OR accordingly. Besides this, there many other handy expressions.

There are two different conditional statements: if statement and case statement.

Primary and combining expressions

Expressions enclosed inside [[ ]] (or [ ] for sh) are called test commands or primaries. These expressions help us to indicate results of a conditional. In the tables below, we are using [ ], because it works for sh too. Here is an answer about the difference between double and single square brackets in bash.

Working with the file system:

Primary Meaning
[ -e FILE ] True if FILE exists.
[ -f FILE ] True if FILE exists and is a regular file.
[ -d FILE ] True if FILE exists and is a directory.
[ -s FILE ] True if FILE exists and not empty (size more than 0).
[ -r FILE ] True if FILE exists and is readable.
[ -w FILE ] True if FILE exists and is writable.
[ -x FILE ] True if FILE exists and is executable.
[ -L FILE ] True if FILE exists and is symbolic link.
[ FILE1 -nt FILE2 ] FILE1 is newer than FILE2.
[ FILE1 -ot FILE2 ] FILE1 is older than FILE2.

Working with strings:

Primary Meaning
[ -z STR ] STR is empty (the length is zero).
[ -n STR ] STR is not empty (the length is non-zero).
[ STR1 == STR2 ] STR1 and STR2 are equal.
[ STR1 != STR2 ] STR1 and STR2 are not equal.

Arithmetic binary operators:

Primary Meaning
[ ARG1 -eq ARG2 ] ARG1 is equal to ARG2.
[ ARG1 -ne ARG2 ] ARG1 is not equal to ARG2.
[ ARG1 -lt ARG2 ] ARG1 is less than ARG2.
[ ARG1 -le ARG2 ] ARG1 is less than or equal to ARG2.
[ ARG1 -gt ARG2 ] ARG1 is greater than ARG2.
[ ARG1 -ge ARG2 ] ARG1 is greater than or equal to ARG2.

Conditions may be combined using these combining expressions:

Operation Effect
[ ! EXPR ] True if EXPR is false.
[ (EXPR) ] Returns the value of EXPR.
[ EXPR1 -a EXPR2 ] Logical AND. True if EXPR1 and EXPR2 are true.
[ EXPR1 -o EXPR2 ] Logical OR. True if EXPR1 or EXPR2 are true.

Sure, there are more useful primaries and you can easily find them in the Bash man pages.

Using an if statement

if statements work the same as in other programming languages. If the expression within the braces is true, the code between then and fi is executed. fi indicates the end of the conditionally executed code.

# Single-line
if [[ 1 -eq 1 ]]; then echo "true"; fi

# Multi-line
if [[ 1 -eq 1 ]]; then
  echo "true"
fi

Likewise, we could use an if..else statement such as:

# Single-line
if [[ 2 -ne 1 ]]; then echo "true"; else echo "false"; fi

# Multi-line
if [[ 2 -ne 1 ]]; then
  echo "true"
else
  echo "false"
fi

Sometimes if..else statements are not enough to do what we want to do. In this case we shouldn't forget about the existence of if..elif..else statements, which always come in handy.

Look at the example below:

if [[ `uname` == "Adam" ]]; then
  echo "Do not eat an apple!"
elif [[ `uname` == "Eva" ]]; then
  echo "Do not take an apple!"
else
  echo "Apples are delicious!"
fi

Using a case statement

If you are confronted with a couple of different possible actions to take, then using a case statement may be more useful than nested if statements. For more complex conditions use case like below:

case "$extension" in
  "jpg"|"jpeg")
    echo "It's image with jpeg extension."
  ;;
  "png")
    echo "It's image with png extension."
  ;;
  "gif")
    echo "Oh, it's a giphy!"
  ;;
  *)
    echo "Woops! It's not image!"
  ;;
esac

Each case is an expression matching a pattern. The | sign is used for separating multiple patterns, and the ) operator terminates a pattern list. The commands for the first match are executed. * is the pattern for anything else that doesn't match the defined patterns. Each block of commands should be divided with the ;; operator.