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

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

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

cat somefile >file1 >file2

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

私の出力をコピーしたり書いたりしない理由を説明してくださいsomefile。 (file2私の出力は含まれていますが、file1何も含まれていません)

答え1

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

zsh出力が複数回リダイレクトされたときに表示されるのと同様の動作を実装する場合を除き、teeシェルの出力を複数回リダイレクトすることはできず、指定したすべての場所にリダイレクトされると期待できません。代わりに、最後の場所にのみリダイレクトされますfile2。あなたの場合、Chaosの答えはI / Oリダイレクトがどのように機能するかについて良い説明を提供します。

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

$ cat example.txt | tee file1 > file2

tee標準入力から読み込み、複数のファイル記述子に書き込むプログラムです。その一つはいつも標準出力。したがって、我々はを使用してtee出力を作成し、file1標準出力をfile2

また、コメントで提案されているように、目的を達成するためのより良い方法は次のとおりです。

$ tee file1 < example.txt > file2

このアプローチの利点は、stdinパイプを通して読み取ろうとする代わりにリダイレクトされることです。これは、シェルが1つのプロセスを生成しなくてはならないことを意味します。いわゆる「猫のごみの利用」も解消されます。配置して出力リダイレクト後ろに入力リダイレクトを使用すると、入力ファイルを開くことができない場合に出力ファイルが破損するのを防ぎます。

答え2

あなたがすることはI/O リダイレクト>fileあなたの場合は、標準出力(stdout)をfile2回リダイレクトしました。シェルは同じ出力のリダイレクトを複数回処理しません。

この場合:

cat somefile >file1 >file2

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

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


tee標準出力を複数のプロセス/ファイルにリダイレクトする方法は次のとおりです。

cat somefile | tee file1 file2 file3 fileX

これにより、内容が標準出力として印刷されます。そして引数として提供されたすべてのファイルに適用されます。

答え3

zsh~とさまざまなオプション設定(デフォルト)を使用できます。

cat somefile >file1 >file2

この場合、zsh後で同様のことを行います。teeでも:

<somefile >file1 >file2

デフォルトでは、$NULLCMDコマンドリダイレクトがないときに実行されるコマンドはまさにそのコマンドですcat

答え4

cat somefile >file1 >file2

リダイレクトがない場合、cat somefilestdinはシェルから継承されます。通常、シェルのstdinは閉じられておらず、すでにファイルを指しています。ターミナルも文書。標準出力が端末であるインタラクティブシェルで実行されると、出力はcat somefile端末catに移動します。一般に、シェルの標準出力は、関連しない他の出力であり、catとにかく継承されます。

それcat somefile >file1がすることはシェルを作ることです:

  • 書き込み用に開いてfile1(ファイルがまだない場合は作成)、0サイズに切り捨てます(可能な場合)。これはcat始める前に起こります。
  • file1将来の標準出力に設定されているため使用されますcatcatfile1 変えるcat somefile >file1リダイレクトなしで何を使用しますか? (端末にも書きたくないですか?)

リダイレクトリダイレクト。 :) 現在の方向は「to 端末」で、新しい方向は「to file1」です。新しい方向をつかむ変える現在の方向と新しい方向が現在の方向になります。

シェルは左から右にリダイレクトを解析します。cat somefile >file1 >file2ケーシングの場合は、>file1まず上記のように進めてください。その後処理します>file2 同じように:ファイルを開いて切り取り、file2将来のために「to」を設定します。cat 変える現在の方向はすでに「to file1」です。これにより、「to」file2が「to」に置き換えられ、file1現在の状態になります。まるでfile1今「to」が「to the Terminal」に置き換えられているのと同じです。

より多くのリダイレクトを追加でき、>fileN各リダイレクトは説明に従って処理されます。誰もが成功すると仮定すると、最後に立っている人が勝ちます。あなたの場合は>file2勝利してください。

すべてのリダイレクトが処理されたらcat起動します。標準出力catに見えますが、何らかの方法で関連しているという事実file2さえ知りません。file1切り捨てはシェルによって解析され、それとは何の関係もないfile1ため、「副作用」です。>file1cat

このメカニズムを使用して、1つ以上のファイルを作成/切り捨てることができます。: >file1 >file2 …ファイルを切り捨てようとします。:動作せず、標準出力も使用しません。シェルが起動する前にリダイレクトを処理すると、作成と切り捨てが発生します:


これはsh互換性のあるシェルで出力リダイレクトが機能する方法です。 MULTIOSオプションzsh(参照この他の答え)は異なります。最初のリダイレクトは前の方向(端末など)を置き換えますが、連続リダイレクトは次へ追加方向。後ろでどのように起こるかは詳しく説明しません。私はあなたが観察した動作がshそれぞれが処理されるという事実(または互換性のあるシェルから)から来ていることを指摘したいと思いました。>fileN独立して、順番に。ただし、zsh単一デバイスのように複数の出力をリダイレクトするモードがあります。

関連情報