如何将一个程序的标准输入作为arg传递给另一个程序?


17

假设存在一个有两个参数的程序;输入文件和输出文件。

如果我不想将此输出文件保存到磁盘上,而是直接将其传递给stdin另一个程序怎么办?有没有办法做到这一点?

我在Linux上遇到的许多命令都提供了一个选项来传递“-”作为输出文件参数,这与我上面指定的功能相同。这是因为stdin无法将程序的作为参数传递吗?如果是,我们该怎么做?

我如何使用此图像的示例是:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" stdin(echo)

我正在使用的外壳是bash。


1
cat <file | cmd /dev/fd/0适用于大多数unices。
mikeserv 2015年

不为我工作。尝试了: cat < README.txt | cp /dev/fd/0。它说cp: missing destination file operand after ‘/dev/fd/0’ Try 'cp --help' for more information.
Dziugas

1
program input-file /dev/stdout | another-program?另请注意,它echo不会从stdin 中读取任何内容。
yaegashi

1
@Dziugas-当然不是-您cp无处不在。echo 1 2 3| cp /dev/fd/0 /dev/tty将打印1 2 3。顺便说一下,与大多数情况/dev/fd/[num]相比,它更有可能起作用/dev/std(in|out|err)。请参阅文件描述符链接的可移植性,以了解可以在哪里工作。
mikeserv

1
一个好的UNIX程序会写到标准输出,然后由用户决定是要重定向到文件还是管道到另一个命令。
Jorge Bucaran 2015年

Answers:


13

如果程序即使无法搜索也支持写入任何文件描述符,则可以将其/dev/stdout用作输出文件。这是/proc/self/fd/1我系统上的符号链接。文件描述符1是stdout。


这解决了我的查询。那么,当程序需要搜索时,有没有办法做到这一点?
Dziugas

3
如果您试图阻止磁盘访问,则可以在/ dev / shm /中写入文件,但是,如果您不希望文件系统上有任何文件,那么据我所知,没有办法继续搜索管道。向前搜索意味着它将必须缓冲内存中的所有内容,直到到达该点为止;而向后搜索则意味着已经缓冲了内存中的所有内容。
TiCPU

pdftotext像许多(但不是全部)其他实用程序-也对此提供支持(即使在不支持/ dev / stdout的系统上也可以使用,或者/ dev / stdout不能按预期运行的系统(如在Linux上不支持stdout的系统)管道)。pdftotext file.pdf - | wc -c
斯特凡Chazelas

11

pdftotext手册页:

如果文本文件为“-”,则将文本发送到stdout。

因此,在这种情况下,您需要做的是:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" -

或者,如果要将其通过管道传递到另一个程序的STDIN:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" - | another_prog

使用-作为替代文件名是一个惯例许多公用事业遵循(包括pdftotext)当我们想从STDIN输入或输出到标准输出。但是,并非所有实用程序都遵循此约定。在那种情况下,bash中惯用的方法是使用进程替换

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( cat )

这里的>( )行为在很大程度上类似于传递给的文件my_utility,但是该流不是通过真实文件发送,而是通过管道传递到所包含进程的标准输入,即cat。因此,此处的文本最终应按要求输出。

在这样的论坛上,cat几乎总是使用UUOC闹钟。我认为,如果该实用程序不支持-,那么这是对有用的用法cat,尽管如果有任何方法可以在不使用的情况下进行此过程替换cat,那么我无不为之;-)。

但是,如果(如问题所述)流的最终目的地是另一个程序的STDIN,则cat可以消除:

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( another_prog )

2
再让我一次回踩:如果prog2写入标准输出,比更好,因为表单等待完成(即,在shell发出下一个提示或继续执行下一个命令之前(例如,在或之后)),而-less形式仅等待完成。此外,在表单之后,是的退出状态,而在另一种是的退出状态。(您付钱,然后选择。)prog1 input_file >( cat ) | prog2prog1 input_file >( prog2 )catprog2;&&catprog1cat$?prog2$?prog1
斯科特

4

如果您的shell支持它们,那么进行这种操作的最简单方法就是使用进程替换<(…)>(…)。这适用于bash,zsh和ksh以及可能的其他shell。例如:

$ sort <(printf "b\nc\na\n")
a
b
c
$ ls
foo
$ cp <(find . -name foo) bar
$ ls
bar  foo

但是,这对您陈述的示例没有帮助,因为pdftotext它将保存在文本文件中。尽管最好的选择(除了使用明显的选择-)是/dev/stdout按照@TiCPU的建议使用,但您也可以使用其他shell功能。该构造!:N引用先前命令的第N个参数。因此,您可以执行以下操作:

$ pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf"  out.txt
$ cat !:2

1
虽然我同意cat <()在某些情况下可能有用,但是在这种情况下它根本无法工作。问题(我必须承认,OP的描述很差)是pdftotext有两个参数:input fileoutput file。如果缺少第二个参数,则不产生任何结果,因此cat <(pdftotext "file.pdf")也将不返回任何内容。可以pdftotext通过给出>(cat)第二个论点来作弊,例如“数字创伤”,但cat <()在这里毫无意义。显然,pdftotext以防万一,最好仅将其-用作输出文件名。
jimmij

1
@Scott我的答案如何?没有cat,您将如何执行此过程替换? >( )可以有效地将流传输到内部的任何进程-因此,我们实际上确实需要在cat此处输出该流。通常,我们应该能够执行类似的操作pdftotext input.pdf -,但显然pdftotext不支持-直接输出到stdout而不是文件的参数-试试吧。
Digital Trauma

1
@DigitalTrauma这不是uuoc。我相信cat仅在打印的情况下是最快的,但是实际上您可以使用其他命令>(grep something)来使它更有用。顺便说一句,我pdftotext 3.04 确实支持将其-作为输出文件,所以整个讨论让我有些惊讶。
jimmij

1
@terdon我讨厌做个stickler,但这似乎行不通。具体来说,运行pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf"与将输出放置在一个名为中的文件没有什么不同C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.txt,但是没有文本输出到STDOUT以便传递到另一个程序。
Digital Trauma 2015年

1
@DigitalTrauma并不是一个粘人!那是我白痴。多谢您指出错误,指出错误时请勿致歉。我宁愿指出我的错误,也要学习一些东西,而不是将其保留在所有可疑的荣耀中。
terdon

-2
cmd tty

tty返回连接到的终端的名称stdout


我不确定这如何回答有关组合命令的问题。也许您会举例说明如何实现这一目标。
dhag 2015年

我想您是说要检查tty终端的名称,然后将该文件用作输出,例如pdftotext file.pdf /dev/pts/2。在那种情况下,我同意。
jimmij

可以缩写为/自动化为; 通常相当于。但是,这种方法假定目标是要显示的输出(即,终端),而不是问题是问什么(见注释terdon的回答了一些澄清这个问题的意思)。prog1  input_file $(tty)prog1  input_file /dev/ttyprog1
Scott
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.