NAME
test
, [
—
validate predicate
SYNOPSIS
test |
[! ] (
expr )
[{-a , -o }
expr]… |
test |
[! ] string
{= , != }
string, file
{-ef , -nt ,
-ot } file
[{-a , -o }
expr]… |
test |
[! ] -t
fd, {-n ,
-z } string,
{-e , -s ,
-f , -d ,
-c , -b ,
-p , -S ,
-O , -G ,
-r , -w ,
-x , -u ,
-g , -k ,
-N } file,
{-h , -L }
path [{-a ,
-o } expr]… |
test |
[! ] integer
{-lt , -le ,
-eq , -ne ,
-ge , -gt }
integer [{-a ,
-o } expr]… |
test |
[! ] string
[{-a , -o }
expr]… |
test |
[ |
[! ] (
expr )
[{-a , -o }
expr]… ] |
[ |
[! ] string
{= , != }
string, file
{-ef , -nt ,
-ot } file
[{-a , -o }
expr]… ] |
[ |
[! ] -t
fd, {-n ,
-z } string,
{-e , -s ,
-f , -d ,
-c , -b ,
-p , -S ,
-O , -G ,
-r , -w ,
-x , -u ,
-g , -k ,
-N } file,
{-h , -L }
path [{-a ,
-o } expr]…
] |
[ |
[! ] integer
{-lt , -le ,
-eq , -ne ,
-ge , -gt }
integer [{-a ,
-o } expr]…
] |
[ |
[! ] string
[{-a , -o }
expr]… ] |
[ |
] |
DESCRIPTION
Exits with the result of the specified boolean expression. With no expression, exits false.
Operators
In chunked descending precedence, except all unary operators are
equiprecedent; -ao
left-associative.
True if:
(
expr)
- expr
!
expr- expr is not true.
- expr
-a
expr - Both expressions are.
- expr
-o
expr - Either expression is.
- string = string
- The strings are identical.
- string != string
- The strings are not identical.
- file
-ef
file - The files correspond to the same file — lie on the same device and point at the same i-node.
- file-l
-nt
file-r - The modification time of file-l is earler than that of file-r.
- file-l
-ot
file-r - The modification time of file-l is later than that of file-r.
-t
fd- File descriptor fd corresponds to a teletype.
-n
string- string is not empty.
-z
string- string is empty.
-e
file- file exists.
-s
file- file's size is non-zero.
-f
file- file is a regular file.
-d
file- file is a directory.
-c
file- file is a character device.
-b
file- file is a block device.
-p
file- file is a named pipe (FIFO).
-S
file- file corresponds to a UNIX-domain socket.
-h
path,-L
path- path is a symbolic link.
-O
file- file is owned by the process' effective user ID.
-G
file- file is owned by the process' effective group ID.
-r
file- file could be read by the process.
-w
file- file could be written by the process.
-x
file- file could be executed (searched) by the process.
-u
file- file is set-user-ID.
-g
file- file is set-group-ID.
-k
file- file is sticky.
-N
file- file's modification time is after its access time.
- int-l
-lt
int-r - int-l < int-r
- int-l
-le
int-r - int-l ≤ int-r
- int-l
-eq
int-r - int-l = int-r
- int-l
-ne
int-r - int-l ≠ int-r
- int-l
-ge
int-r - int-l ≥ int-r
- int-l
-gt
int-r - int-l > int-r
- string
-n
string
EXIT STATUS
- 0
- The expression evaluated true.
- 1
- The expression evaluated false.
- 2
- Syntax error in expression or non-integer passed to
-t
or an arithmetic operator.
EXAMPLES
A short, edited, extract from kernel-install(8):
#!/bin/sh[
-z
"
$MACHINE_ID
"]
&&
[
-f
/etc/machine-id]
&&
read
-r
MACHINE_ID
<
/etc/machine-id[
-z
"
$MACHINE_ID
"]
&&
MACHINE_ID
=Default[
"
$VERBOSE
"-ge
3]
&&
echo
"Machine ID
:$MACHINE_ID
"for
suff
in
"
$MACHINE_ID
" "Default" "loader/entries";do
for
pref
in
"/efi" "/boot" "/boot/efi"
;do
if
[
-d
"
$pref/$suff
"]
;then
BOOT_ROOT
="$pref
"break
2fi
done
done
if
[
-z
"
$layout
"]
;then
if
[
-d
"
$BOOT_ROOT/$MACHINE_ID
"]
;then
layout
="bls-efi"else
layout
="legacy"fi
fi
SEE ALSO
STANDARDS
Conforms to IEEE Std 1003.1-2008
(“POSIX.1”); -O
,
-G
, -k
,
-ef
, -nt
,
and -ot
are extensions;
-k
originates from CB-UNIX,
-N
from
bash(1), the rest from the KornShell,
The standard marks ()
and
-ao
as obsolete, and for good reason — the
expression grammar is very loose and easy to throw off with malicious input.
Chain multiple test
invocations with
&&
and ||
instead,
though be wary of precedence (rather, the comparative lack thereof without
an explicit {}
).
HISTORY
Appears prototypically in Version 2 AT&T UNIX as if(I):
NAME
if -- conditional command
SYNOPSIS
if expr command [ arg1 ... ]
- !
- unary negation operator
- -a
- binary and operator
- -o
- binary or operator
- (
expr
) - parentheses for grouping.
-c
as present-day, including
-ao
precedence.
The BUGS state:
Version 3 AT&T UNIX removes
-c
.
Version 5 AT&T UNIX adds an expr of
if
exclusion would hint at funny business, but there
is none — everything up to the }
is passed to
execv(2) in the child, with the period-appropriate
PATH
emulation. This makes
if
{
whatever a b c }
something q w eif
whatever a
b c; then
something q w
e; fi
Version 7 AT&T UNIX makes
if
a reserved word in the shell, as present-day, and
replaces
if(I) with test
supporting
()
, !
,
-ao
, =
,
!=
, -tnzsfdrw
,
-lt
, -le
,
-eq
, -ne
,
-ge
, -gt
,
and the plain string. -t
,
when not followed by an argument, defaults to -t
1. -lt
,
-le
, -eq
,
-ne
, -ge
,
-gt
, instead of integers, can be provided with
-l
string, resolving to the
length of string.
CB-UNIX at or before version 2.3 adds
-xcbugk
and drops -l
.
CB-UNIX was, among others, the basis for AT&T System III UNIX, which sees the same implementation, but, curiously, only as a sh(1) built-in.
AT&T System V Release 1
UNIX adds -p
. AT&T
System V Release 4 UNIX adds
-h
, alters -f
to match any
non-directories if /usr/ucb is in the
PATH
.
4.4BSD adds all CB-UNIX operators,
-eph
, and &|
as aliases
for -ao
to a Version 7
AT&T UNIX base.
Version 7 AT&T UNIX accepts
being called as [
, undocumented in the manual, but
only if it takes up the whole argument 0 (is not preceded
by a path).
CB-UNIX adds the [
expr ]
syntax to the
manual.
4.4BSD checks only the final character.
IEEE Std 1003.1-2008 (“POSIX.1”) requires checking the basename, previous standards are unclear.