少文件 1 文件 2 | 猫——它为什么有效?

tfh*_*tfh 21 less pipe cat

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

Mic*_* D. 31

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

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

有一个名为“isa tty ”的 C 函数,它检查输出是否将进入 tty(小于 4.81,main.c,第 112 行)。如果是这样,它使用缓冲区查看器,否则它的行为就像cat.

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

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

例子:

[[ -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'
Run Code Online (Sandbox Code Playgroud)


Pet*_*des 7

less检查它stdout是否是一个终端,并且cat在它不是时的行为(将 stdin 复制到 stdout 直到 EOF)。

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

less如果您在向管道添加更多阶段时忘记从单行代码中编辑它,那么类似猫的行为会很方便。


less需要弄清楚终端尺寸(屏幕尺寸,知道一次显示多少行)。将ioctl(2)它使用在stdout将在非终端返回ENOTTY,所以它不能避免反正处理非终端情况。 less实际上isatty(3)在检查终端尺寸之前使用,但isatty通过尝试仅 tty 的 ioctl 并检查是否缺少错误来工作。

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


请注意,当您通过管道将某些内容导入 less(例如grep foo bar.txt | less)时,它确实必须打开/dev/tty以进行键盘输入。(你可以看到它用 来做到这一点echo foo | strace less)。