if: run something only when a condition holds
if runs a block only when a test succeeds. The shape is always the same, and fi (if backwards) closes it:
n=7
if [ "$n" -gt 5 ]; then
echo "$n is big"
fiIn the terminal
student@vulntech:~$ n=7 student@vulntech:~$ if [ "$n" -gt 5 ]; then > echo "$n is big" > fi 7 is big
The [ ... ] is the test command. It checks one thing and succeeds or fails, and if acts on the result. The spaces inside the brackets are required.
else and elif
hour=14
if [ "$hour" -lt 12 ]; then
echo "Good morning"
elif [ "$hour" -lt 18 ]; then
echo "Good afternoon"
else
echo "Good evening"
fiIn the terminal
student@vulntech:~$ hour=14 student@vulntech:~$ if [ "$hour" -lt 12 ]; then > echo "Good morning" > elif [ "$hour" -lt 18 ]; then > echo "Good afternoon" > else > echo "Good evening" > fi Good afternoon
Testing numbers
| Test | True when |
|---|---|
[ "$a" -eq "$b" ] | a equals b |
[ "$a" -ne "$b" ] | a is not equal to b |
[ "$a" -lt "$b" ] | a is less than b |
[ "$a" -le "$b" ] | a is less than or equal to b |
[ "$a" -gt "$b" ] | a is greater than b |
[ "$a" -ge "$b" ] | a is greater than or equal to b |
Testing files
These are the checks you'll use most in real scripts, deciding whether a file or folder is there before touching it:
| Test | True when |
|---|---|
[ -e path ] | It exists (file or folder) |
[ -f path ] | It's a regular file |
[ -d path ] | It's a folder |
[ -r path ] / -w / -x | You can read / write / run it |
[ -s path ] | It exists and isn't empty |
if [ -d /etc ] && [ ! -f /etc/nope ]; then
echo "/etc is a folder and /etc/nope does not exist"
fiIn the terminal
student@vulntech:~$ if [ -d /etc ] && [ ! -f /etc/nope ]; then > echo "/etc is a folder and /etc/nope does not exist" > fi /etc is a folder and /etc/nope does not exist
&& joins two tests (and), || means or, and a ! inside the brackets flips a test to mean not.
Testing strings
| Test | True when |
|---|---|
[ "$a" = "$b" ] | The strings are equal |
[ "$a" != "$b" ] | They're different |
[ -z "$a" ] | a is empty |
[ -n "$a" ] | a is not empty |
word=""
if [ -z "$word" ]; then
echo "nothing was set"
fiIn the terminal
student@vulntech:~$ word="" student@vulntech:~$ if [ -z "$word" ]; then > echo "nothing was set" > fi nothing was set
Common mistake: Always quote the variables in a test. If
$ais empty,[ $a = yes ]becomes[ = yes ]and errors;[ "$a" = yes ]is fine.
Remember:
if [ test ]; then ... elif [ test ]; then ... else ... fi. Numbers use-gt,-eq; files use-f,-d; and always quote your variables.