Tests & Conditionals

Conditionals

if [ -f /etc/passwd ]; then
  echo 'exists'
elif [ -d /tmp ]; then
  echo 'dir'
else
  echo 'neither'
fi

That [ ... ] inside the if isn't special if syntax - it's actually a command in its own right (historically a program literally named test, with [ as an alias for it that requires a matching ] at the end). It runs the check you give it and exits with status 0 (true, per the exit-code convention you'll meet fully in a later section) or non-zero (false); if is just watching that exit status.

TestTrue when
-f filefile exists (regular)
-d dirdirectory exists
-e pathpath exists (any type)
-r/-w/-xreadable/writable/executable
-z strstring is empty
-n strstring is non-empty
n1 -eq n2numbers equal (-ne -lt -le -gt -ge)
s1 = s2strings equal (!= not equal)
$ [ 5 -gt 3 ] && echo yes
yes

This one-liner works because [ 5 -gt 3 ] is a normal command with an exit status, and && (from the redirection module's cousin, the logic operators) only runs echo yes if the command before it succeeded.

Warning: Bash has two entirely separate sets of comparison operators, and mixing them up produces confusing results without any error message: use -eq, -lt, -gt etc. for numbers, and =/!= for strings. [ "10" -gt "9" ] correctly compares numerically (true), while [ "10" \> "9" ] would compare as strings, alphabetically - where "10" actually sorts before "9" character by character. Also always quote your variables inside [ ] ([ "$a" = "$b" ]) - an unquoted variable that happens to be empty collapses to nothing, turning [ $a = foo ] into the malformed [ = foo ] and causing a syntax error precisely when you're testing the edge case that matters most.