Classic Shell Scripting - Arnold Robbins [74]
* * *
test, [ ... ]
Usage
test [ expression ]
[ [ expression ] ]
Purpose
To test conditions in shell scripts, returning results via the exit status. Note that in the second form of the command, the brackets are typed literally, and must be separated from the enclosed expression by whitespace.
Major options and expressions
See Table 6-6 and text.
Behavior
test tests file attributes, compares strings, and compares numbers.
Caveats
The expressions mandated by POSIX are a subset of what is often available on real systems. Care is required for full portability. More information is provided in Section 14.3.2.
Except on absolutely ancient Unix systems, test is built into the shell. Since built-in commands are found before external commands, this makes it difficult to write simple test programs that produce an executable named test. Such programs must be invoked as ./test (assuming they're in the current directory).
* * *
The test command has a variant form: [ ... ]. It works identically to the test command. Thus, these two statements test two strings for equality:
if test "$str1" = "$str2" if [ "$str1" = "$str2" ]
then then
... ...
fi fi
POSIX describes the arguments to test as "expressions." There are unary and binary expressions. The unary expressions consist of what look likes an option (e.g., -d to test if a file is a directory) with a corresponding operand; typically, but not always, a filename. The binary expressions have two operands with an embedded operator that performs some sort of comparison. Furthermore, when there is only a single argument, test checks to see if it is the null string. The full list is provided in Table 6-6.
Table 6-6. test expressions
Operator
True if ...
string
string is not null.
-b file
file is a block device file.
-c file
file is a character device file.
-d file
file is a directory.
-e file
file exists.
-f file
file is a regular file.
-g file
file has its setgid bit set.
-h file
file is a symbolic link.
-L file
file is a symbolic link. (Same as -h.)
-n string
string is non-null.
-p file
file is a named pipe (FIFO file).
-r file
file is readable.
-S file
file is a socket.
-s file
file is not empty.
-t n
File descriptor n points to a terminal.
-u file
file has its setuid bit set.
-w file
file is writable.
-x file
file is executable, or file is a directory that can be searched.
-z string
string is null.
s1 = s2
Strings s1 and s2 are the same.
s1 != s2
Strings s1 and s2 are not the same.
n1 -eq n2
Integers n1 and n2 are equal.
n1 -ne n2
Integers n1 and n2 are not equal.
n1 -lt n2
n1 is less than n2.
n1 -gt n2
n1 is greater than n2.
n1 -le n2
n1 is less than or equal to n2.
n1 -ge n2
n1 is greater than or equal to n2.
Tests may be negated by preceding them with !. Here are some sample tests in action:
if [ -f "$file" ]
then
echo $file is a regular file
elif [ -d "$file" ]
then
echo $file is a directory
fi
if [ ! -x "$file" ]
then
echo $file is NOT executable
fi
XSI-conformant systems have a more complicated version of test. Expressions can be combined with -a (for logical AND) and with -o (for logical OR). -a has higher precedence than -o, and = and != have higher precedence than the other binary operators. Parentheses may be used for grouping and to change evaluation order.
* * *
Tip
There is a difference between using -a and -o, which are test operators, and && and ||, which are shell operators.
if [ -n "$str" -a -f "$file" ] Two conditions, one test command
if [ -n "$str" ] && [ -f "$file ] Two commands, short-circuit evaluation
if [ -n "$str" && -f "$file" ] Syntax error, see text
In