The test command can be a shell builtin or file executable (if you specify the full path to the file) that is used for file comparison, it returns a status of 0 (true) or 1 (false) depending on the evaluation of the conditional expression EXPR.
It can be used to check file types, string operator, and numeric comparison operators.
If you run the test command as is, the exit status will be 1, try running test and echo the exit status, you'll get the following:
user@server:~$ test user@server:~$ echo $? 1
$? is used to check exit status ID of a command. The test command will always return True or False or 0 or 1, depending on if the expression is true or not. The syntax of the test command is:
To Inverse the expression, you use:
test ! EXPRESSION
To include multiple expressions, e.g the AND and OR, you can use the following:
test EXPRESSION -a EXPRESSION
test EXPRESSION -o EXPRESSION
Alternatively, you can use a shorthand version, which replaces test with opening and closing square brackets. For example, instead of
test -z $1
[ -z $1 ]
See how handy that is, however, you must make sure the square brackets are separate arguments. If you do [-z $1], it would treat everything as a whole command, so, again, separate the argument: [ EXPR ]
Testing File Types
File type option test for a particular file type, you can test if a directory exists before performing an action or check if a file exists at all, here are some options:
- -b FILE: Test if FILE exists and is a block special device
- -c FILE: Test if FILE exists and is a character special device.
- -d FILE: Test if FILE exists and is a directory.
- -f FILE: Test if FILE exists and is a regular file.
- -L FILE or -h FILE: Test if FILE exists and is a symbolic link. Unlike all other
file-related tests, this test does not dereference FILE if it is a
- -p FILE: Test if FILE exists and is a named pipe.
- -S FILE: Test if FILE exists and is a socket.
- -t FD: True if FD is a file descriptor that is associated with a terminal.
Access Permission Tests
This options test for file permissions, you can test if certain permission exists before performing an action, here are some options:
- -g FILE: True if FILE exists and has its set-group-ID bit set.
- -k FILE: True if FILE exists and has its “sticky” bit set.
- -r FILE: True if FILE exists and read permission is granted.
- -u FILE: True if FILE exists and has its set-user-ID bit set.
- -w FILE: True if FILE exists and write permission is granted.
- -x FILE: True if FILE exists and execute permission is granted (or search
permission, if it is a directory).
- -O FILE: True if FILE exists and is owned by the current effective user ID.
- -G FILE: True if FILE exists and is owned by the current effective group ID.
File Characteristic Tests
This is one of my favorite options, imagine you want to check certain modification on a file before performing an action, an example is checking file date, and then performing an action based on that, here are some options:
- -e FILE: True if FILE exists.
- -s FILE: True if FILE exists and has a size greater than zero.
- FILE1 -nt FILE2: True if FILE1 is newer (according to modification date) than FILE2,
or if FILE1 exists and FILE2 does not.
- FILE1 -ot FILE2: True if FILE1 is older (according to modification date) than FILE2,
or if FILE2 exists and FILE1 does not.
- FILE1 -ef FILE2: True if FILE1 and FILE2 have the same device and inode numbers,
i.e., if they are hard links to each other.
This can be used to check for string characteristics or to test for the equality or inequality of two strings. Consider the following example:
[ $USER = root ]
The above example checks if the current user is root, you can also write it this way:
test $USER = root, this syntax can be confusing, at least to me, so, I'll use the former for the rest of the examples.
We could also test for a non-root account with the following method:
[ ! $USER = root ]
Here are more options...
- -z STRING: True if the length of STRING is zero.
- -n STRING: True if the length of STRING is nonzero.
- STRG1 = STRG2: True if the strings are equal.
- STRG1 == STRG2: True if the strings are equal (synonym for =).
- STRG1 != STRG2: True if the strings are not equal.
Say, you want to confirm the user input or to test if a variable is set, you can do:
[ -z $1 ]
Testing isn't limited to a string, you can also test for integer values and whole numbers. Another way of testing input of a script is to count the numbers of positional parameters and also test that the number is above 0:
[ $# -gt 0 ]
$# Can be used to get the total number of arguments passed to script, so, when we check if the value is gt (greater than) zero, we are basically checking if the argument is set, another example:
[ 5 -gt -2 ] && echo yes
If 5 is greater the 2, echo yes!
Here are more options:
- ARG1 -eq ARG2: True if ARG1 is equal to ARG2
- ARG1 -ne ARG2: True if ARG1 is not-equal to ARG2
- ARG1 -lt ARG2: True if ARG1 is lesser-than to ARG2
- ARG1 -le ARG2: True if ARG1 is less-than-or-equal to ARG2
- ARG1 -gt ARG2: True if ARG1 is greater-to ARG2
- ARG1 -ge ARG2: True if ARG1 is greater-than-or-equal to ARG2
I'll keep referencing this page as it would be handy when writing conditional script.