How To Use Test Conditions Within A Bash Script

man typing on keyboard
dm909/Moment/Getty Images

Introduction

The test command can be used on the Linux command line to compare one element against another but it is more commonly used in BASH shell scripts as part of conditional statements which control logic and program flow.

A Basic Example

You can try these commands simply by opening a terminal window.

test 1 -eq 2 && echo "yes" || echo "no"

The above command can be broken down as follows:

  • test - this means you are about to perform a comparison
  • 1 - the first element you are going to compare
  • -eq (how are you comparing, in this case you are testing whether one number equals another)
  • 2 - the element you are comparing the first element again 
  • && - run the following statement if the result is true
  • echo "yes" - the command to run if the comparison returns true
  • || - run the following statement if the result is false
  • echo "no" - the command to run if the comparison returns false

In essence the command is comparing 1 to 2 and they match the echo "yes" statement is executed which displays "yes" and if they do not match the echo "no" statement is executed which displays "no".

Comparing Numbers

If you are comparing elements that parse as numbers you can use the following comparison operators:

  • -eq - does value 1 equal value 2
  • -ge - is value 1 greater or equal to value 2
  • -gt - is value 1 greater than value 2
  • -le - is value 1 less than or equal to value 2
  • -lt - is value 1 less than value 2
  • -ne - does value 1 not equal value 2

Examples:

test 1 -eq 2 && echo "yes" || echo "no"

(displays "no" to the screen because 1 does not equal 2)

test 1 -ge 2 && echo "yes" || echo "no"

(displays "no" to the screen because 1 is not greater or equal to 2)

test 1 -gt 2 && echo "yes" || echo "no" 

(displays "no" to the screen because 1 is not greater than 2)

test 1 -le 2 && echo "yes" || echo "no" 

(displays "yes" to the screen because 1 is less than or equal to 2)

test 1 -lt 2 && echo "yes" || echo "no" 

(displays "yes" to the screen because 1 is less than or equal to 2)

test 1 -ne 2 && echo "yes" || echo "no" 

(displays "yes" to the screen because 1 does not equal 2)

Comparing Text

If you are comparing elements that parse as strings you can use the following comparison operators:

  • = - does string 1 match string 2
  • != - is string 1 different to string 2
  • -n - is the string length greater than 0
  • -z - is the string length 0

Examples:

test "string1" = "string2" && echo "yes" || echo "no"

(displays "no" to the screen because "string1" does not equal "string2")

test "string1" != "string2" && echo "yes" || echo "no"

(displays "yes" to the screen because "string1" does not equal "string2")

test -n "string1" && echo "yes" || echo "no"

(displays "yes" to the screen because "string1" has a string length greater than zero)

test -z "string1" && echo "yes" || echo "no"

(displays "no" to the screen because "string1" has a string length greater than zero)

Comparing Files

If you are comparing files you can use the following comparison operators:

  •  -ef - Do the files have the same device and inode numbers (are they the same file)
  • -nt - Is the first file newer than the second file
  • -ot - Is the first file older than the second file
  • -b - The file exists and is block special
  • -c - The file exists and is character special
  • -d - The file exists and is a directory
  • -e - The file exists
  • -f - The file exists and is a regular file
  • -g - The file exists and has the specified group number
  • -G - The file exists and owner by the user's group
  • -h - The file exists and is a symbolic link
  • -k - The file exists and has its sticky bit set
  • -L - The same as -h
  • -O - The file exists you are the owner
  • -p - The file exists and is a named pipe
  • -r - The file exists and is readable
  • -s - The file exists and has a size greater than zero
  • -S - The file exists and is a socket
  • -t - The file descriptor is opened on a terminal
  • -u - The file exists and the set-user-id bit is set
  • -w - The file exists and is writable
  • -x - The file exists and is executable

Examples:

test /path/to/file1 -n /path/to/file2 && echo "yes"

(If file1 is newer than file2 then the word "yes" will be displayed)

test  -e /path/to/file1  && echo "yes"

(if file1 exists the word "yes" will be displayed)

test  -O /path/to/file1  && echo "yes"

(if you own file1 then the word "yes" is displayed")

Terminology

  • Block special - The file is a block device which means that data is read in blocks of bytes. These are generally device files such as hard drives.
  • Character special - The file is acted upon immediately when you write to it and is commonly a device such as a serial port

Comparing Multiple Conditions

Thus far everything has been comparing one thing against another but what if you want to compare two conditions.

For example if an animal has 4 legs and goes "moo" it is probably a cow. Simply checking for 4 legs doesn't guarantee that you have a cow but checking the sound it makes surely does.

To test both conditions at once use the following statement:

test 4 -eq 4 -a "moo" = "moo" && echo "it is a cow" || echo "it is not a cow"

The key part here is the -a which stands for and.

There is a better and more commonly used way of performing the same test and that is as follows:

test 4 -eq 4 && test "moo" = "moo" && echo "it is a cow" || echo "it is not a cow"

Another test you might want to make is compare two statements and if either is true output a string. For example if you want to check that a file named "file1.txt" exists or a file called "file1.doc" exists you can use the following command

test -e file1.txt -o -e file1.doc && echo "file1 exists" || echo "file1 does not exist"

The key part here is the -o which stands for or.

There is a better and more commonly used way of performing the same test and that is as follows:

test -e file1.txt || test -e file1.doc && echo "file1 exists" || echo "file1 does not exist"

Eliminating The Test Keyword

You don't actually need to use the word test to perform the comparison. All you have to do is enclose the statement is square brackets as follows:

[ -e file1.txt ] && echo "file1 exists" || echo "file1 does not exist"

The [ and ] basically means the same as test.

Now you know this you can improve on comparing multiple conditions as follows:

[ 4 -eq 4 ] && [ "moo" = "moo" ] && echo "it is a cow" || echo "it is not a cow"

[ -e file1.txt ] || [ -e file1.doc ] && echo "file1 exists" || echo "file1 does not exist"

Summary

The test command is more useful in scripts because you can test the value of one variable against another and control program flow. On the standard command line you can use it to test whether a file exists or