Page Body

Checking File Types and Comparing Values With the test Command

The test command can be used to compare either numbers or strings, and to check file properties via numerous tests.

test ex_expression

Each test returns either a 0 (True) or 1 (False).

The test command supports an abbreviated notation where the expression to be evaluated is enclosed in double brackets (with spaces after and before the brackets), e.g., [[ ex_expression ]]. Often, this shorthand notation is used in scripts.

An expression can be negated by placing the logical NOT operator before it (!), e.g., test ! ex_expression.

The logical AND (&&) and logical OR (||) operators can be used to join multiple expressions, e.g., test ex_expression_1 && test ex_expression_2. The logical AND operator has precedence over the logical OR operator.

The logical operators are supported within the [[ ex_expression ]] syntax, as well:

  • [[ ! ex_expression ]]
  • [[ ex_expression_1 && ex_expression_2 ]]
  • [[ ex_expression_1 || ex_expression_2 ]]

Note: If you are not familiar with the GNU/Linux command line interface, review the Conventions page before proceeding.

Internal and External test Commands

On your GNU/Linux system, there will likely be both an internal and external version of the test command. Usually, the external command is the version your shell will end up using when you employ test.

For example, on Debian, the version of test that is used (unless otherwise specified) is located at /usr/bin/test. To use the internal version of test, you can use the builtin command (e.g., builtin test). This tells your shell that you intend to use the internal version of the test command.

Examples

Supplying a variable name to test as an argument makes the command check whether or not the variable is non-empty, i.e., whether or not the variable contains a value.

$ test "${PATH}" && echo 'Not empty!' || echo 'Empty!'
Not empty!

Above, we test whether or not the PATH variable has a value. If it does have a value, the test "${PATH}" command will return a 0, which will cause the execution of the echo 'Not empty!' command via the use of the logical AND operator (i.e., &&). This tells us that the PATH variable is not empty. If PATH was empty, the echo 'Empty!' command would have been executed instead, via the use of the logical OR operator (i.e., ||).

The value that a test command returns can be verified by displaying the contents of the ? variable:

$ test "${PATH}" ; echo "${?}"
0

The next example tests whether the variable x contains a value greater than 20:

$ x='15'
$ test "${x}" -gt 20 ; echo "${?}"
1

Since 15 is less than 20, the test "${x}" -gt 20 command returns a 1 (False).

The following example checks whether the value in the variable x sorts after the character d based on lexicographic ordering:

$ x='a'
$ builtin test "${x}" \> 'd' ; echo "${?}"
1

Since a comes before d in a lexicographic sort, test "${x}" \> 'd' returns 1 (False).

The final example checks whether a .bashrc file in the current user's home directory exists and is readable:

$ test -r "${HOME}/.bashrc" ; echo "${?}"
0

${HOME}/.bashrc exists and is readable, so test -r "${HOME}/.bashrc" returns 0 (True).

Tests

The test command supports:

  • Arithmetic tests
  • File tests
  • Shell tests
  • String tests

Arithmetic Tests

ex_integer_1 -eq ex_integer_2
ex_integer_1 is equal to ex_integer_2.
ex_integer_1 -ge ex_integer_2
ex_integer_1 is greater than or equal to ex_integer_2.
ex_integer_1 -gt ex_integer_2
ex_integer_1 is greater than ex_integer_2.
ex_integer_1 -le ex_integer_2
ex_integer_1 is less than or equal to ex_integer_2.
ex_integer_1 -lt ex_integer_2
ex_integer_1 is less than ex_integer_2.
ex_integer_1 -ne ex_integer_2
ex_integer_1 is not equal to ex_integer_2.

In regard to the order of operations, BEDMAS is observed:

  1. Brackets/Braces/Parentheses
  2. Exponents
  3. Division
  4. Multiplication
  5. Addition
  6. Subtraction

File Tests

The following file tests use unary operators, i.e., they require one file (argument) to test.

-a ex_file
True if ex_file exists. Equivalent to -e. This test is for use with the internal version of the test command.
-b ex_file
True if ex_file exists and is a block special file.
-c ex_file
True if ex_file exists and is a character special file.
-d ex_file
True if ex_file exists and is a directory.
-e ex_file
True if ex_file exists. Equivalent to -a.
-f ex_file
True if ex_file exists and is a regular file.
-g ex_file
True if ex_file exists and its setgid bit is set.
-G ex_file
True if ex_file exists and is owned by the effective group ID (EGID).
-h ex_file
True if ex_file exists and is a symbolic link. Equivalent to -L.
-k ex_file
True if ex_file exists and its sticky bit is set.
-L ex_file
True if ex_file exists and is a symbolic link. Equivalent to -h.
-N ex_file
True if ex_file exists and has been modified since it was last read.
-O ex_file
True if ex_file exists and is owned by the effective user ID (EUID).
-p ex_file
True if ex_file exists and is a named pipe (FIFO, First In First Out).
-r ex_file
True if ex_file exists and is readable.
-s ex_file
True if ex_file exists and its size is greater than zero.
-S ex_file
True if ex_file exists and is a socket.
-t ex_file_descriptor
True if ex_file_descriptor is open and refers to a terminal.
-u ex_file
True if ex_file exists and its setuid bit is set.
-w ex_file
True if ex_file exists and is writable.
-x ex_file
True if ex_file exists and is executable.

These file tests use binary operators, i.e., they require two files (arguments) to test.

ex_file_1 -ef ex_file_2
True if ex_file_1 and ex_file_2 refer to the same device and inode numbers (hard link test).
ex_file_1 -nt ex_file_2
True if ex_file_1 is newer (according to modification date) than ex_file_2, or if ex_file_1 exists and ex_file_2 does not.
ex_file_1 -ot ex_file_2
True if ex_file_1 is older than ex_file_2 (according to modification date), or if ex_file_2 exists and ex_file_1 does not.

Shell Tests

The following tests are for use with the internal version of the test command.

-o ex_option_name
True if the shell option ex_option_name is enabled.
-R ex_variable
True if the shell variable ex_variable is set and is a name reference.
-v ex_variable
True if the shell variable ex_variable is set (i.e., has been assigned a value).

In contrast to the external version of test, when using the internal version, do not include the $ when referencing variables (e.g., builtin test -v 'PATH' ; echo "${?}").

String Tests

ex_string_1 == ex_string_2
True if ex_string_1 and ex_string_2 are equal, e.g., [[ 'a' == 'a' ]].
ex_string_1 != ex_string_2
True if ex_string_1 and ex_string_2 are not equal.
ex_string_1 < ex_string_2
True if ex_string_1 sorts before ex_string_2 lexicographically, e.g., [[ 'a' < 'b' ]]. This test is for use with the internal version of the test command.
ex_string_1 > ex_string_2
True if ex_string_1 sorts after ex_string_2 lexicographically. This test is for use with the internal version of the test command.
-n ex_string
True if the length of ex_string is non-zero.
-z ex_string
True if the length of ex_string is zero, e.g., [[ -z 'GNU/Linux' ]].

Documentation

For more information on the test command, refer to its man page, either from the command line, or online.

Enjoyed this post?

Subscribe to the feed for the latest updates.