web-dev-qa-db-ja.com

複数のファイルへのコマンドリダイレクト:コマンド> file1> file2

私はこのコマンドを持っています:

cat somefile >file1 >file2

このコマンドを実行した後、なぜfile1には何も含まれていません。最初のファイル(somefile)の出力があるはずですが、その中には何もありません。

somefileからの出力がコピーまたは書き込まれない理由を教えてください。 (file2には出力が含まれますが、file1には何も含まれません)

9
Charlie Albert

シェルリダイレクトの動作と実際の動作には違いがあると思います。

シェルの出力を複数回リダイレクトして、指定したすべての場所にリダイレクトされることを期待することはできません。代わりに、最後の場所(この場合はfile2)にのみリダイレクトされます。カオスの答えは、そのようなI/Oリダイレクトがどのように機能するかについての適切な説明を提供します。

あなたが本当にやりたいことは:

$ cat example.txt | tee file1 > file2

teeは、標準入力から読み取り、複数のファイル記述子に書き込むプログラムです。それらの1つはalways標準出力です。したがって、teeを使用して出力をfile1に書き込み、そのstdoutをfile2にリダイレクトします。

また、コメントの提案に基づいて、これはあなたが探していることを行うためのより良い方法です:

$ tee file1 > file2 < example.txt

このアプローチには、パイプを介して読み取るのではなく、stdinをリダイレクトするという利点があります。つまり、シェルは1つ少ないプロセスを生成する必要があります。また、「猫の無用」と呼ばれるものも排除します。

15
darnir

あなたがしたことは I/O-Redirection と呼ばれます。 >fileは、標準出力(stdout)を指定されたfileにリダイレクトします。あなたの場合、あなたはそれを2回行いました。シェルは、同じ出力のリダイレクトを複数回処理しません。

この場合:

cat somefile >file1 >file2

シェルは、コマンド(cat somefile)が実行される前にリダイレクトを処理します。つまり、ファイルのコンテンツを上書きするため、>はファイルを長さゼロに切り捨てます。シェルがコマンドを実行する前に、ファイルは空でなければなりません。これは、両方の>リダイレクトで行われます。

これで、シェルはリダイレクトを表示順に処理するため、2番目の(>file2)が最初の(>file1)をオーバーライドします。だから、最後のものは効果的に使われるものです。したがって、cat somefileの出力はfile2にリダイレクトされ、file1は長さがゼロに切り捨てられます。


Stdoutを複数のプロセス/ファイルにリダイレクトするには、次のようにteeを使用します。

cat somefile | tee file1 file2 file3 fileX

これは、内容を標準出力およびに、パラメーターとして指定されたすべてのファイルに出力します。

9
chaos

zshMULTIOSオプションセット を使用すると、次のように使用できます。

cat somefile >file1 >file2

この場合と同様に、zshアクションはteeと同様です。

2
cuonglm