.TH test "" "" Command
.PC "Evaluate conditional expression"
\fBtest \fIexpression ...\fR
.PP
.HS
.SH Options:
.IC "\fB! \fIexp\fR"
Negate logical value of \fIexp\fR
.IC "\fIstring1 \fB!= \fIstring2\fR"
\fIstring1\fR does not equal \fIstring2\fR
.IC "\fIstring1 \fB< \fIstring2\fR"
\fIstring1\fR is lexicographically less than \fIstring2\fR
(\fBsh\fR only)
.IC "\fIstring1 \fB= \fIstring2\fR"
\fIstring1\fR equals \fIstring2\fR
.IC "\fIstring1 \fB> \fIstring2\fR"
\fIstring1\fR is lexicographically greater than \fIstring2\fR
(\fBsh\fR only)
.IC "\fB(\fIexp\^\fB)\fR"
Parentheses group expressions
.IC "\fIexp1 \fB\-a\fI exp2\fR"
Both expressions are true
.IC "\fB\-b \fIfile\fR"
\fIfile\fR is block-special
.IC "\fB\-c \fIfile\fR"
\fIfile\fR is character-special
.IC "\fB\-d \fIfile\fR"
\fIfile\fR is a directory
.IC "\fB\-e \fIfile\fR"
\fIfile\fR exists (\fBsh\fR only)
.IC "\fIfile1 \fB\-ef\fI file2\fR"
Files are identical
.IC "\fIn1 \fB\-eq\fI n2\fR"
Numbers are equal
.IC "\fB\-f \fIfile\fR"
\fIfile\fR exists and is an ordinary file
.IC "\fB\-g \fIfile\fR"
\fIfile\fR has \fBsetgid\fR bit set
.IC "\fIn1 \fB\-ge\fI n2\fR"
\fIn1\fR is greater than or equal to \fIn2\fR
.IC "\fIn1 \fB\-gt\fI n2\fR"
\fIn1\fR greater than \fIn2\fR
.IC "\fB\-k \fIfile\fR"
\fIfile\fR has sticky bit set
.IC "\fB\-L \fIfile\fR"
\fIfile\fR is a symbolic link
.IC "\fIn1 \fB\-le\fI n2\fR"
\fIn1\fR is less than or equal to \fIn2\fR
.IC "\fIn1 \fB\-lt\fI n2\fR"
\fIn1\fR is less than \fIn2\fR
.IC "\fB\-n \fIstring\fR"
\fBstring\fR has non-zero length
.IC "\fIn1 \fB\-ne\fI n2\fR"
\fIn1\fR does not equal \fIn2\fR
.IC "\fIf1 \fB\-nt \fIf2\fR"
\fIf1\fR is newer than \fIf2\fR
.IC "\fIexp1 \fB\-o\fI exp2\fR"
Either \fIexp1\fR or \fIexp2\fR is true
.IC "\fIf1 \fB\-ot\fI f2\fR"
\fIf1\fR is older than \fIf2\fR
.IC "\fB\-p \fIfile\fR"
\fIfile\fR is a named pipe
.IC "\fB\-r \fIfile\fR"
\fIfile\fR is readable
.IC "\fB\-s \fIfile\fR"
\fIfile\fR exists and has nonzero length
.IC "\fB\-t \fI[fd]\fR"
\fIfd\fR describes a terminal
.IC "\fB\-u \fIfile\fR"
\fIfile\fR has \fBsetuid\fR set
.IC "\fB\-w \fIfile\fR"
\fIfile\fR is writable
.IC "\fB\-x \fIfile\fR"
\fIfile\fR is executable
.IC "\fB\-z \fIstring\fR"
\fIstring\fR has zero length
.IC "\fIstring\fR"
\fIstring\fR has non-zero length
.HE
.B test
evaluates an
.IR expression ,
which consists of string comparisons, numerical comparisons,
and tests of file attributes.
For example, a
.B test
command might be used within a shell script to test whether a certain
file exists and is readable.
.PP
The logical result (true or false) of the
.I expression
is returned by the command for use by another shell construct, such as the
command
.BR if .
.PP
Under the Korn shell,
.B test
is a built-in command that returns zero if
.I expression
is true, and one if it is false.
Under the Bourne shell,
.B test
is not a built-in command;
rather, the Bourne shell uses the command
.B /bin/test
to test expressions.
.B /bin/sh
returns zero if the expression is true, one if it is false, and two if
a syntax error (or other error) occurred.
.SH "Expression Options"
.B test
recognizes the following options, one or more of which can be built into an
.IR expression :
.IP "\fB! \fIexp\fR" 1.2i
Negates the logical value of expression
.IR exp .
.IS "\fIstring1 \fB!=\fR \fIstring2\fR"
.I string1
is not equal to
.IR string2 .
.IS "\fIstring1 \fB< \fIstring2\fR"
.I string1
is lexicographically less than
.I string2
(\fBsh\fR only).
.IS "\fIstring1 \fB= \fIstring2\fR"
.I string1
is equal to
.IR string2 .
.IS "\fIstring1 \fB> \fIstring2\fR"
.I string1
is lexicographically greater than
.I string2
(\fBsh\fR only).
.IS "\fB(\fIexp\^\fB)\fR"
Parentheses allow expression grouping.
.IS "\fIexp1 \fB\-a\fI exp2\fR"
Both expressions
.I exp1
and
.I exp2
are true.
.IS "\fB\-b \fIfile\fR"
.I file
is a block-special device.
.IS "\fB\-c \fIfile\fR"
.I file
is a character-special file.
.IS "\fB\-d \fIfile\fR"
.I file
exists and is a directory.
.IS "\fB\-e \fIfile\fR"
.I file
exists (\fB/bin/test\fR only).
.IS "\fIfile1 \fB\-ef\fI file2\fR"
.I file1
is the same file as
.IR file2 .
.IS "\fIn1 \fB\-eq\fI n2\fR"
Numbers
.I n1
and
.I n2
are equal.
Please note that
.B test
evalutes the expression
.B ""
as zero.
Thus, if one of the arguments is a variable that is not set,
.B test
treats it as if it were zero.
For example, consider the expression:
.DM
	if [ "$notset" -eq 0 ]
.DE
.IS
If
.B notset
is not set,
.B test
evaluates it to zero and so returns
.BR true .
.IS "\fB\-f \fIfile\fR"
.I file
exists and is an ordinary file.
.IS "\fB\-g \fIfile\fR"
File mode has
.B setgid
bit.
.IS "\fIn1 \fB\-ge\fI n2\fR"
Number
.I n1
is greater than or equal to
.I n2.
.IS "\fIn1 \fB\-gt\fI n2\fR"
Number
.I n1
is greater than
.IR n2 .
.IS "\fB\-k \fIfile\fR"
File mode has sticky bit.
.IS "\fB\-L \fIfile\fR"
File is a symbolic link.
.IS "\fIn1 \fB\-le\fI n2\fR"
Number
.I n1
is less than or equal to
.I n2.
.IS "\fIn1 \fB\-lt\fI n2\fR"
Number
.I n1
is less than
.I n2.
.IS "\fB\-n \fIstring\fR"
.I string
has nonzero length.
.IS "\fIn1 \fB\-ne\fI n2\fR"
Numbers
.I n1
and
.I n2
are not equal.
.IS "\fIfile1 \fB\-nt \fIfile2\fR"
.I file1
is newer than
.IR file2 .
.IS "\fIexp1 \fB\-o\fI exp2\fR"
Either expression
.I exp1
or
.I exp2
is true.
.B \-a
has greater precedence than
.BR \-o .
.IS "\fIfile1 \fB\-ot\fI file2\fR"
.I file1
is older than
.IR file2 .
.IS "\fB\-p \fIfile\fR"
.I file
is a named pipe.
.IS "\fB\-r \fIfile\fR"
.I file
exists and is readable.
.IS "\fB\-s \fIfile\fR"
.I file
exists and has nonzero size.
.\" .IS "\fB\-S \fIfile\fR"
.\" .I file
.\" is a socket.
.\" .B ksh
.\" only.
.IS "\fB\-t \fI[fd]\fR"
.I fd
is the file descriptor number of a file that is open and a terminal.
The Bourne shell requires that
.I fd
be given; under the Korn shell, however,
defaults to the standard output
(file descriptor 1) if no
.I fd
is given.
.IS "\fB\-u \fIfile\fR"
File mode has
.B setuid
set.
.IS "\fB\-w \fIfile\fR"
.I file
exists and is writable.
.IS "\fB\-x \fIfile\fR"
.I file
exists and executable.
.IS "\fB\-z \fIstring\fR"
.I string
has zero length (is a null string).
.IS \fIstring\fR
.I string
has nonzero length.
.SH "Implementations of test"
The implementation of
.B test
under the Bourne shell has been rewritten for \*(CO release 4.2,
both to extend its range of features and to make it more compliant with
published standards.
Although this makes
.B test
more useful to programmers, it may create problems when you try to
execute a Bourne-shell script written under \*(CO release 4.2
on an earlier release of \*(CO.
The following describes how the Bourne shell's implementation of
.B test
was designed; and how it differs both from earlier implementations under
the Bourne shell and from the implementation under the Korn shell.
.PP
To begin, the Bourne shell's implementation of
.B test
attempts to comply with the \*(PX, comply with previous \*(CO releases of
.BR test ,
and comply with System-V \*(UN to the greatest extent possible.
However, these objectives are mutually exclusive.
See the \*(PX P1003.2/D11.2 \(sc4.62, especially the Rationale,
for details of some of the problems.
In particular,
System V and Berkeley differ in the way they parse some expressions,
which leads the \*(PX to specify test behavior for a minimal set of expressions,
.I not
including
.B \-a
and
.BR \-o .
.PP
The following details differences among the various implementations of
.BR test .
First, the following options were not
implemented in the Bourne shell's implementation of
.B test
prior to \*(CO release 4.2, but
were included in the Korn shell's implementation:
.BR \-b ,
.BR \-c ,
.BR \-ef ,
.BR \-g ,
.BR \-k ,
.BR \-L ,
.BR \-nt ,
.BR \-ot ,
.BR \-p ,
.BR \-u ,
and
.BR \-x .
Of these, the following are not described in the \*(PX:
.BR \-k ,
.BR \-L ,
.BR \-ef ,
.BR \-nt ,
and
.BR \-ot .
Note that Bourne-shell scripts that use any of the above options to
.B test
will
.I not
run on versions of \*(CO prior to release 4.2, but will run under the
Korn shell.
.PP
Next, the Bourne shell for \*(CO 4.2 implements the \*(PX's option
.B \-e
and the options
.B <
and
.BR > .
Bourne-shell scripts that use any of these three options to
.B test
will
.I not
run on versions of \*(CO prior to release 4.2, nor will they run under
the Korn shell.
.PP
The definitions of the options
.B \-f
and
.B \-t
have been changed from the Berkeley standard to that described in the \*(PX.
Berkeley defines
.B \-f
as meaning that a file exists and is not a directory; whereas the \*(PX
defines it as meaning that a file exists and is a regular file.
Versions of the Bourne shell prior to \*(CO 4.2
use the Berkeley definitions; whereas all version of the Korn shell
and Bourne shell under \*(CO 4.2 use the \*(PX's definition.
Berkeley gives
.B \-t
a default value of one if it is not used with an argument; whereas
the \*(PX requires that
.B \-t
have an argument.
The Korn shell and all versions of the Bourne shell prior to \*(CO 4.2
use the Berkeley definition; whereas the Bourne shell under \*(CO 4.2
uses the \*(PX's definition.
These differences are subtle, but important.
Thus, a Bourne shell script that uses either of these options may not run
correctly when imported into \*(CO 4.2 from earlier versions of
\*(CO, or when exported from \*(CO 4.2 to them or to the Korn shell.
.\" Lord, make my hands the same ...
.PP
Finally,
.B test
under the Korn shell and under the Bourne shell prior to \*(CO 4.2 returns
zero if an expression is true and one either if the expression
is false or if the expression contained a syntax error.
However,
.B test
under the Bourne shell for \*(CO 4.2 returns zero if an expression
is true, one if it is false, and two if a syntax error occurred.
Bourne-shell scripts that pay close attention to what
.B test
returns may not run correctly when imported into \*(CO 4.2 from earlier
implementations of \*(CO, or when exported from \*(CO 4.2 to earlier
versions of \*(CO or to the Korn shell.
.SH Example
The following example uses the
.B test
command to determine whether a file is writable.
.DM
	if test ! \-w /dev/lp
	then
		echo The line printer is inaccessible.
	fi
.DE
.PP
Under \*(CO, the command `[' is linked to
.BR test .
If invoked as `[',
.B test
checks that its last argument is `]'.
This allows an alternative syntax:
simply enclose
.I expression
in square brackets.
For example, the above example can be written as follows:
.DM
	if [ ! \-w /dev/lp ]
	then
		echo The line printer is inaccessible.
	fi
.DE
.PP
For a more extended example of the square-bracket syntax, see
.BR sh .
.SH "See Also"
.Xr "commands," commands
.Xr "expr," expr
.Xr "find," find
.Xr "if," if.c
.Xr "ksh," ksh
.Xr "sh," sh
.Xr "while" while.c
.SH Notes
The Korn shell's version of this command is based on the public-domain
version written by Erik Baalbergen and Arnold Robbins.
