我的理解是pipe
,例如,
command1 | command2
command1
将的输出发送至command2
。但是,我希望这能起作用:
echo "tmp.pdf" | evince
但事实并非如此。echo "tmp.pdf"
发送的输出在哪里?
答案1
你的理解是正确的。该序列command1 | command2
将 的输出 (STDOUT) 发送command1
到 的输入 (STDIN) command2
。您的evince
命令不起作用的原因是它evince
不接受 STDIN 上的文件名。
答案2
管道将其输出发送到打开它以供读取的程序。在 shell 管道中,这是管道符号右侧的程序,即evince
在您的示例中。
您正在发送文件名tmp.pdf
以在其标准输入上显示。然而 evince 并不关心它的标准输入。与每个作用于文件的程序一样,它期望文件名作为命令行参数传递;如果您不在命令行上传递文件名,它会提供打开文件的功能。命令行参数与标准输入不同。人类有不同的输入器官来输入不同的东西(例如,你不能通过鼻子吃东西),同样,程序有不同的方式来接收用于不同目的的信息。
Evince 可以阅读文件(不是文件名)在标准输入上:evince /dev/stdin <"tmp.pdf"
. (这可能不适用于所有 Unix 变体。)文件名的/dev/stdin
意思是“您已经在标准输入上打开的任何文件”。用于命令行的程序通常在没有给出文件名的情况下读取其标准输入,但 GUI 程序通常不会。 Evince 只能以这种方式打开常规文件,而不能打开来自管道的数据(例如cat tmp.pdf | evince /dev/stdin
不起作用),因为它需要能够在页面之间导航时在文件中来回查找。
答案3
正如我最近自己意识到的那样,您可以按如下方式绕过这个问题。首先使用locate命令查找您希望在evince中打开的文件的路径。然后将此结果作为参数传递到evince中。假设您的文件名是abc_xyz.pdf并且您希望打开它。然后你就可以做-
evince "$(sudo locate xyz | grep abc)"
.请注意,如果您的 pdf 文件的名称包含空格,那么您需要双引号 The $(sudo locate xyz | grep abc)
Reason Why I am using another code (piped with sudo locate xyz
) iegrep abc
是为了进一步过滤结果。但这里有一个问题,那就是,您需要通过发出不断更新locate sudo updatedb
。假设您将 pdf 的位置更改为某个新目录,然后locate 将无法找到 itz 新位置,因为 itz 数据库尚未更新。但是您可以使用带有“and”条件的“find”命令来完成实时搜索的工作。例如你可以这样做-
evince "$(find ~/ -iname "*abc*" -a -iname "*xyz*" -type f)"
并将其作为参数传递给 evince.here 参数-iname
用于不区分大小写的搜索,并且-a
是和条件。-type f
只会返回文件。