> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/man1/test.1.md).

# test(1)

`test` — 条件评估实用程序

## 名称

`test`, `[`

## 概要

`[ expression [ expression ]`

## 描述

`[` 实用程序评估表达式，如果评估为真，返回零（真）退出状态；否则返回 1（假）。如果没有表达式，`[` 也返回 1（假）。

所有运算符和标志都是 `[` 实用程序的独立参数。

以下主表达式用于构造表达式：

**`-b`** `file` 如果 `file` 存在且是块特殊文件，则为真。

**`-c`** `file` 如果 `file` 存在且是字符特殊文件，则为真。

**`-d`** `file` 如果 `file` 存在且是目录，则为真。

**`-e`** `file` 如果 `file` 存在（不论类型），则为真。

**`-f`** `file` 如果 `file` 存在且是常规文件，则为真。

**`-g`** `file` 如果 `file` 存在且其 set group ID 标志已设置，则为真。

**`-h`** `file` 如果 `file` 存在且是符号链接，则为真。保留此运算符是为了与该程序的先前版本兼容。不要依赖它的存在；改用 `-L`。

**`-k`** `file` 如果 `file` 存在且其粘滞位已设置，则为真。

**`-n`** `string` 如果 `string` 的长度非零，则为真。

**`-p`** `file` 如果 `file` 是命名管道（FIFO），则为真。

**`-r`** `file` 如果 `file` 存在且可读，则为真。

**`-s`** `file` 如果 `file` 存在且大小大于零，则为真。

**`-t`** `file_descriptor` 如果文件描述符号为 `file_descriptor` 的文件已打开且与终端关联，则为真。

**`-u`** `file` 如果 `file` 存在且其 set user ID 标志已设置，则为真。

**`-w`** `file` 如果 `file` 存在且可写，则为真。为真仅表示写标志已开启。即使此测试为真，在只读文件系统上文件也不可写。

**`-x`** `file` 如果 `file` 存在且可执行，则为真。为真仅表示执行标志已开启。如果 `file` 是目录，为真表示可以搜索 `file`。

**`-z`** `string` 如果 `string` 的长度为零，则为真。

**`-L`** `file` 如果 `file` 存在且是符号链接，则为真。

**`-O`** `file` 如果 `file` 存在且其所有者与此进程的有效用户 ID 匹配，则为真。

**`-G`** `file` 如果 `file` 存在且其组与此进程的有效组 ID 匹配，则为真。

**`-S`** `file` 如果 `file` 存在且是套接字，则为真。

**`file1`** `-nt` `file2` 如果 `file1` 存在且比 `file2` 新，则为真。

**`file1`** `-ot` `file2` 如果 `file1` 存在且比 `file2` 旧，则为真。

**`file1`** `-ef` `file2` 如果 `file1` 和 `file2` 存在且引用同一文件，则为真。

**`string`** 如果 `string` 不是空字符串，则为真。

**`s1`** `=` `s2` 如果字符串 `s1` 和 `s2` 相同，则为真。

**`s1`** `!=` `s2` 如果字符串 `s1` 和 `s2` 不相同，则为真。

**`s1`** `<` `s2` 如果基于字符的二进制值，字符串 `s1` 排在 `s2` 之前，则为真。

**`s1`** `>` `s2` 如果基于字符的二进制值，字符串 `s1` 排在 `s2` 之后，则为真。

**`n1`** `-eq` `n2` 如果整数 `n1` 和 `n2` 代数相等，则为真。

**`n1`** `-ne` `n2` 如果整数 `n1` 和 `n2` 代数不相等，则为真。

**`n1`** `-gt` `n2` 如果整数 `n1` 代数大于整数 `n2`，则为真。

**`n1`** `-ge` `n2` 如果整数 `n1` 代数大于或等于整数 `n2`，则为真。

**`n1`** `-lt` `n2` 如果整数 `n1` 代数小于整数 `n2`，则为真。

**`n1`** `-le` `n2` 如果整数 `n1` 代数小于或等于整数 `n2`，则为真。

如果 `file` 是符号链接，`[` 将完全解引用它，然后对引用的文件评估表达式，`-h` 和 `-L` 主表达式除外。

这些主表达式可以与以下运算符组合：

**`!`** `expression` 如果 `expression` 为假，则为真。

**`expression1`** `-a` `expression2` 如果 `expression1` 和 `expression2` 都为真，则为真。

**`expression1`** `-o` `expression2` 如果 `expression1` 或 `expression2` 为真，则为真。

**`(`** `expression` `)` 如果 expression 为真，则为真。

`-a` 运算符的优先级高于 `-o` 运算符。

某些 shell 可能提供与此实用程序类似或相同的内建 `[` 命令。参见 [builtin(1)](/man1/builtin.1.md) 手册页。

## 语法歧义

`[` 语法本质上是歧义的。为确保一定程度的一致性，IEEE Std 1003.2 ("POSIX.2") 第 D11.2/4.62.4 节中描述的情况根据标准文档中指定的规则一致地评估。所有其他情况受命令语义歧义的影响。

特别是，只有包含 `-a`、`-o`、`(` 或 `)` 的表达式才可能产生歧义。

## 退出状态

`[` 实用程序以以下值之一退出：

**0** 表达式评估为真。

**1** 表达式评估为假或缺少表达式。

**>1** 发生错误。

## 实例

仅使用 POSIX 功能实现 `test FILE1 -nt FILE2`：

```sh
test -n "$(find -L -- FILE1 -prune -newer FILE2 2>/dev/null)"
```

这可以使用非标准的 [find(1)](/man1/find.1.md) 主表达式（如 `-newerca`）修改，以比较其他时间戳。

## 兼容性

为了与其他一些实现兼容，`=` 主表达式可以用 `==` 替代，含义相同。

## 参见

[builtin(1)](/man1/builtin.1.md), expr(1), [find(1)](/man1/find.1.md), [sh(1)](/man1/sh.1.md), [stat(1)](/man1/stat.1.md), [symlink(7)](/man7/symlink.7.md)

## 标准

`[` 实用程序实现了 IEEE Std 1003.2 ("POSIX.2") 规范的超集。主表达式 `<`、`==`、`>`、`-ef`、`-nt`、`-ot`、`-G` 和 `-O` 是扩展。

## 历史

`[` 实用程序出现在 Version 7 AT\&T UNIX 中。

## 缺陷

在 `-a` 和 `-o` 中，两侧总是会被评估。例如，即使前一个表达式为假，以下命令仍会测试 `file` 的可写状态，这导致对文件系统的不必要访问：

```sh
[ -z abc -a -w file ]
```

为避免此问题，请写为

```sh
[ -z abc ] && [ -w file ]
```
