Bash If Else

Conditional logic in Bash uses if/then/elif/else/fi blocks together with test conditions to branch on the outcome of a command.

Basic if/then/fi Structure

A Bash conditional starts with if, followed by a condition, then then on the same line or after a semicolon, a block of commands, and a closing fi (if spelled backwards). The condition is really just a command; if it exits with status 0 (success) the then block runs, otherwise it is skipped.

Example

#!/bin/bash
disk_free=12

if [ "$disk_free" -lt 20 ]; then
  echo "Warning: low disk space (${disk_free}GB free)"
fi

Adding elif and else

else provides a fallback branch when the condition is false, and elif (else-if) lets you test additional conditions in order without nesting more if blocks. Bash evaluates each condition top to bottom and runs only the first matching branch.

Example

#!/bin/bash
temp=72

if [ "$temp" -lt 60 ]; then
  echo "Cold"
elif [ "$temp" -le 80 ]; then
  echo "Comfortable"
else
  echo "Hot"
fi

Test Conditions: [ ], [[ ]], and test

The square brackets [ condition ] are actually a call to the test command; [[ condition ]] is a Bash keyword with the same purpose but fewer quoting pitfalls and extra pattern-matching features. Conditions can check numbers, strings, or files, and can be combined with && (and) and || (or).

  • -f file -- true if file exists and is a regular file
  • -d dir -- true if dir exists and is a directory
  • -e path -- true if path exists (any type)
  • -x file -- true if file is executable
  • -z str / -n str -- true if string is empty / non-empty

Example

#!/bin/bash
config="/etc/app.conf"

if [ -f "$config" ] && [ -r "$config" ]; then
  echo "Config file is present and readable"
else
  echo "Cannot read config file"
fi
Note: Always put a space after [ and before ] -- [ $x -gt 0 ] works, but [$x -gt 0] fails because [ is itself a command name.
Note: Bash has no "else if" -- the correct keyword is elif. Writing else if starts a nested if block that then needs its own extra fi.

Exercise: Bash If Else

Which keyword must be used to close every `if` block in Bash?