当我使用时,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
)。