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.
| Test | True when |
|---|---|
-f file | file exists (regular) |
-d dir | directory exists |
-e path | path exists (any type) |
-r/-w/-x | readable/writable/executable |
-z str | string is empty |
-n str | string is non-empty |
n1 -eq n2 | numbers equal (-ne -lt -le -gt -ge) |
s1 = s2 | strings 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,-gtetc. 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.