进一步阅读

进一步阅读

如果我这样做ls | lessls会检测到它没有连接到终端,这很公平。除了那个less 连接到终端。在此设置中,ls可以生成针对终端的彩色和列化输出,并less可以正确处理它。您可以使用 使颜色正常工作ls --color=force | less -r,但这需要更多的打字,而且它不做列。

如果有一个开关可以less告诉连接到它的任何东西,将其视为真正的终端,那就太酷了。因此,您可以ls | less -T在 中获取彩色和列式列表less

  1. 有做过这样的事吗?

  2. less像它这样的寻呼机实际上可以自己做到这一点,还是需要外壳程序的配合?例如,shell 是否需要设置一个伪终端来ls连接?

答案1

它是设置管道的外壳。less不参与其中。

当您这样做时ls | less,shell 会在创建最终将执行管道写入端的进程的标准输出和将执行同一管道的读取端的进程的标准输入后同时ls启动。lesslsless

ls检测到其标准输出不是 tty 设备,并相应地改变其行为。less对此我们无能为力。

什么是可以做的是使用伪终端对而不是管道来连接两个进程,但这将是一个坏主意,因为伪终端不是为此设计的。其一,断开连接会产生问题。less如果它的标准输入是伪终端主机,可能会感到困惑。

ls另一种方法是获得第三个进程,该进程通过伪终端对读取输出并less通过管道将其输入,例如@JdeBPptyrunptybandage, 或expect'sunbuffer或 using zsh'szpty内置函数:

zmodload zsh/zpty
ttypager() { (zpty c "stty raw -echo; ${(q)@}"; zpty -r c) | less -RFX; }

ttypager ls

ls将在新终端的新会话中运行,因此当您按 ^C 时不会收到 SIGINT,或者less在完成写入之前退出时不会收到 SIGPIPE。然而,由于在这些情况下,持有主端(这里是子 shell)的进程仍然ls会收到 SIGHUP 并死掉。

zpty这里运行命令就像使用 一样eval,因此别名将被扩展。实际上,即使您调用ttypager \lsasttypager仍会收到ls参数并稍后执行别名扩展,它们也会被扩展。

另请注意,stdout 和 stderr 都会进入该伪终端并最终进入管道。

这仍然是一个肮脏的黑客行为。在这里,最简单的方法是告诉ls其行为就像连接到终端一样。

您可以使用辅助函数,例如:

paged_ls() { ls -C --color=always "$@" | less -RFX; }

where-C强制按列输出(ls当输出到达终端时,包括 GNU 在内的某些实现默认执行此操作)并--color=always强制以颜色输出,无论输出是否到达终端。

答案2

执行此操作的一般方法是使用 Bernstein 等工具ptybandage

$ptybandage ls > 摆动 ;更少的摆动

或者,在这种情况下更好,伯恩斯坦的ptyrun

$ptyrun ls |较少的

进一步阅读

相关内容