あるプログラムの標準入力を引数として別のプログラムに渡すにはどうすればよいですか?


17

2つの引数を取るプログラムが存在するとします。入力ファイルと出力ファイル。

この出力ファイルをディスクに保存するのではなくstdin、別のプログラムに直接渡す場合はどうなりますか。これを達成する方法はありますか?

Linuxで出くわす多くのコマンドには、出力ファイルの引数として「-」を渡すオプションがあります。これは、上記で指定したことを行います。これstdinは、プログラムのを引数として渡すことができないためですか?もしそうなら、どうすればいいのでしょうか?

これを使用してどのようにイメージするかの例は次のとおりです。

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

私が使用しているシェルはbashです。


1
cat <file | cmd /dev/fd/0ほとんどの大学で動作します。
mikeserv

私のために働いていません。で試してみました 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からは何も読み取らないことに注意してください。
八重ashi

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プログラムは標準出力に書き込み、ユーザーに任せて、ファイルにリダイレクトするか、別のコマンドにパイプするかを決定します。
ホルヘブカラ

回答:


13

プログラムがシークできない場合でもファイル記述子への書き込みをサポートしている場合は/dev/stdout、出力ファイルとして使用できます。これは/proc/self/fd/1私のシステムへのシンボリックリンクです。ファイル記述子1は標準出力です。


これでクエリが解決しました。だから、プログラムがシークする必要があるときにそれを行う方法はありませんか?
Dziugas

3
ディスクアクセスを防止しようとしている場合は、/ dev / shm /にファイルを書き込むことができますが、ファイルシステム上にファイルが必要ない場合は、私が知る限り、検索する方法はありませんパイプ。前方にシークすると、そのポイントに前方に達するまでメモリ内のすべてをバッファリングする必要があり、後方にシークすると、メモリ内のすべてをバッファリングしたことを意味します。
TiCPU

pdftotext他の多くの(すべてではない)ユーティリティ-も同様にサポートしています(/ dev / stdoutをサポートしていないシステムでも、または/ dev / stdoutが期待どおりに動作しない場合でも、stdoutがサポートされていないLinuxパイプ)。pdftotext file.pdf - | wc -c
ステファンシャゼル

11

pdftotextmanページから:

テキストファイルが「-」の場合、テキストは標準出力に送信されます。

したがって、この場合に必要なのは次のとおりです。

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

または、これを別のプログラムのSTDINにパイプする場合:

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

-ファイル名の代わりに使用することは、STDINからの入力またはSTDOUTへの出力が必要な場合に多くのユーティリティ(pdftotextを含む)が従う慣例です。ただし、すべてのユーティリティがこの規則に従うわけではありません。その場合、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
そして、もう一度話を戻しましょう:prog2stdoutへの書き込みは、フォームが完了するまで待機するため(つまり、シェルが次のプロンプトを発行する前、または次のコマンドに進む前(たとえば、または))、-lessフォームは完了するのを待ちます。また、フォームの後はからの終了ステータスで、もう一方はからの終了ステータスです。(あなたはお金を払って、あなたの選択を取ります。)prog1 input_file >( cat ) | prog2prog1 input_file >( prog2 )catprog2;&&catprog1cat$?prog2$?prog1
スコット

4

シェルがそれらをサポートしている場合、そのような操作を行う最も簡単な方法は、プロセス置換を使用することです:<(…)および>(…)。これは、bash、zsh、kshおよびその他のシェルで機能します。例えば:

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

ただし、これはpdftotextテキストファイルに保存されるため、この例では役に立ちません。@TiCPUで提案され-ている/dev/stdoutように使用するのが(明らかなを使用することは別として)最良の選択ですが、別のシェル機能を使用することもできます。コンストラクト!:Nは、前のコマンドのN番目の引数を参照します。したがって、次のことができます。

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

1
cat <()状況によっては有用であることに同意しますが、このシナリオでは、まったく機能しません。問題(OPによる非常に不十分な記述、認めざるを得ない)は、入力ファイル出力ファイルのpdftotext 2つの引数を取ることです。2番目の引数がない場合、何も生成されないため、何も返されません。Digital Traumaが回答したように、2番目の引数としてコマンドをだますことができますが、ここでは無意味です。明らかに、出力ファイル名として使用するのが最善の場合です。cat <(pdftotext "file.pdf")pdftotext>(cat)cat <()pdftotext-
jimmij

1
@Scott私の答えはUUOCですか?猫なしでこのプロセス置換をどのように行いますか? >( )は、ストリームを内部のプロセスに効果的にパイプcatします。そのため、実際にストリームを出力するにはhere が必要です。通常pdftotext input.pdf -、次のようなことができるはずですが、ファイルではなくstdoutに直接出力するパラメーターをpdftotextサポートしていない-ようです。試してみてください。
デジタル外傷

1
@DigitalTrauma uuocではありません。ただ印刷する場合に猫はあなたが手に入れることができる最速だと思いますが、実際には>(grep something)もっと便利になるように他のコマンドを使うことができます。ところで、私のpdftotext 3.04 行う支援を-、私は少しは全体の議論で驚いているので、出力ファイルとして。
jimmij

1
@terdon私は執事になることを嫌いますが、これはうまくいかないようです。具体的には、running pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf"と呼ばれるファイルに出力を配置するrunning と違いはありませC BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.txtんが、別のプログラムにパイピングするためにテキストがSTDOUTに出力されることはありません。
デジタル外傷

1
@DigitalTrauma、それはステッカーではありません!それは私がばかであることです。それを指摘してくれてありがとう、そして間違いを指摘するときは決して謝らないでください。自分の間違いを指摘してもらい、疑わしい栄光を残してそこに何かを残したいのです。
テルドン

-2
cmd tty

ttyに接続されている端末の名前を返しますstdout


これが質問にどのように答えるかはわかりませんが、それはコマンドの組み合わせに関するものです。おそらく、あなたはそれを達成する方法の例で拡張します。
dhag

tty端末の名前を確認し、そのファイルを出力として使用するように言っているのではないでしょうかpdftotext file.pdf /dev/pts/2。その場合、私は同意します。
ジミジ

これは、次のように短縮/自動化できます。これは一般的にに相当します。しかし、このアプローチは、目標が(つまり、端末で)出力を表示することであり、それが質問の内容ではないことを前提としています(質問の意味についての明確な説明については、terdonの回答に関するコメントを参照)。prog1  input_file $(tty)prog1  input_file /dev/ttyprog1
スコット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.