少 file1 file2 |猫——为什么它有效?

少 file1 file2 |猫——为什么它有效?

当我使用时,less file1 file2我得到了“较少缓冲区查看器”中显示的两个文件,但less file1 file2 | cat打印了附加到标准输出的两个文件的内容。 less 如何知道它是否应该显示“less 缓冲区查看器”或为下一个命令生成到 stdout 的输出?使用什么机制来做到这一点?

答案1

less将文本打印到标准输出。标准输出去

  • 到一个终端(/dev/tty?) 并打开默认的缓冲区查看器
  • 通过一个管道当使用 | 将其管道传输到另一个程序时( less text | cut -d: -f1)
  • 到一个文件less text > tmp当使用 > ( )重定向它时

有一个 C 函数称为“isa终端" 它检查输出是否发送到 tty(小于 4.81,main.c,第 112 行)。如果是,则使用缓冲区查看器,否则其行为类似于cat.

在 bash 中您可以使用测试(参见man test

  • -t FD 文件描述符 FD 在终端上打开
  • -p 文件存在并且是命名管道

例子:

[[ -t 1 ]] && \
    echo 'STDOUT is attached to TTY'

[[ -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a pipe'

[[ ! -t 1 && ! -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a redirection'

答案2

less检查它是否stdout是终端,并cat在不是终端时表现得像(将 stdin 复制到 stdout 直到 EOF)。

此功能使您可以编写始终发送其输出(例如--help输出)的脚本或程序,less同时仍然允许轻松重定向到文件。如果some_command --fullhelp > help.txt仍然等待标准输入上的空格键来翻阅文本或其他内容,那就太糟糕了。一些命令(例如man)检查它们自己的输出,以决定是否通过寻呼机发送它们的输出。如果你运行man ls > ls.txt,它永远不会调用你的$PAGER.

less如果您在向管道添加更多阶段时忘记将其从一行中编辑出来,则类似猫的行为会很方便。


less需要计算出终端尺寸(屏幕尺寸,了解一次显示多少行)。这ioctl(2)它使用 onstdout会在非终端上返回 ENOTTY,因此无论如何它都无法避免处理非终端情况。 less实际上使用isatty(3)在检查终端尺寸之前,但isatty通过尝试仅 tty 的 ioctl 并检查是否有错误来工作。

即使像这样的简单寻呼机more(1)(至少是 util-linux 版本)也具有此功能,因为它可能是针对这种情况实现的最简单的理智行为。


请注意,当您通过管道传输某些内容时进入 less(例如grep foo bar.txt | less),它必须打开/dev/tty以进行键盘输入。 (您可以看到它使用 执行此操作echo foo | strace less)。

相关内容