gunzip < 100terabytes.txt.gz | less
Run Code Online (Sandbox Code Playgroud)
less(1)
根据需要读取尽可能多的行以填满您的屏幕,然后停止到read(2)
. 结果,当管道变满时gunzip(1)
被阻塞write(2)
。
当您向下滚动时,less(1)
问题read(2)
一次又一次,并且随着管道被消耗,gunzip(1)
允许发出write(2)
. 您可以完全灵活地在此处来回切换(假设gunzip < 100terabytes.txt.gz
未完成。)
到目前为止一切都很好。
你可以开始在文本搜索中less(1)
使用/
。但是当在 中找不到搜索字符串时100terabytes.txt
,less(1)
基本上变得无响应。您可以使用 终止搜索Ctrl-C
。但它似乎关闭了gunzip(1)
和之间的管道less(1)
。我不喜欢这个。gunzip(1)
在我放弃文本搜索后,我想手动向下滚动以消耗更多行。这可能吗?
我不是在寻求类似的建议gunzip < 100terabytes.txt.gz | grep pattern | less
你可以尝试 od -v /dev/zero | less
当您按下 时Ctrl+C,整个 shell作业(进程组)都会接收 SIGINT,less
拦截它以中止搜索,但gunzip
会终止。为了避免这种情况,你可以这样做:
(trap '' INT; gunzip < file.gz) | less
Run Code Online (Sandbox Code Playgroud)
这样就忽略了 SIGINT,但请注意,此后gunzip
您将无法再中断。gunzip
对于gunzip
,这可能没问题,因为您需要做的就是退出,less
下次gunzip
它写入某些内容时就会因 SIGPIPE 而死亡,但对于只是挂起而不输出某些内容的应用程序,这将是一个更大的问题(您仍然会不过可以用于Ctrl+ZSIGTSTP 或Ctrl+\SIGQUIT)。
另请注意,某些命令例如pv
或ping
安装它们自己的 SIGINT 处理程序,这将恢复我们的trap '' INT
.
您可以创建一个函数来保存输入,例如:
iless() {
(trap '' INT; "$@") | less
}
iless gunzip < file.gz
Run Code Online (Sandbox Code Playgroud)
或者:
noint() (trap '' INT; "$@")
noint gunzip < file.gz | less
Run Code Online (Sandbox Code Playgroud)
但请注意,对于:
gunzip < file.gz | grep foo | less
Run Code Online (Sandbox Code Playgroud)
你需要写它:
noint gunzip < file.gz | notint grep foo | less
Run Code Online (Sandbox Code Playgroud)
或者:
noint eval 'gunzip < file.gz | grep foo' | less
Run Code Online (Sandbox Code Playgroud)
或者:
iless eval 'gunzip < file.gz | grep foo'
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用进程替换:
less -f <(gunzip < file.gz | grep foo)
Run Code Online (Sandbox Code Playgroud)
或(尽管不在 中zsh
):
less < <(gunzip < file.gz | grep foo)
Run Code Online (Sandbox Code Playgroud)
在这些情况下,shell 不会在前台进程组中的进程替换中包含命令(除了 for 的第二种情况zsh
)。它们的进程组与 shell 的进程组相同。这意味着当您按 时他们不会收到 SIGINT Ctrl+C。
请注意,这些进程不会受到Ctrl+Z或Ctrl+\的影响。
在zsh
、ksh93
和中进行了测试bash
。