私は次のコマンドを持っています:
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)をfile
2回リダイレクトしました。シェルは同じ出力のリダイレクトを複数回処理しません。
この場合:
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 somefile
stdinはシェルから継承されます。通常、シェルのstdinは閉じられておらず、すでにファイルを指しています。ターミナルも文書。標準出力が端末であるインタラクティブシェルで実行されると、出力はcat somefile
端末cat
に移動します。一般に、シェルの標準出力は、関連しない他の出力であり、cat
とにかく継承されます。
それcat somefile >file1
がすることはシェルを作ることです:
- 書き込み用に開いて
file1
(ファイルがまだない場合は作成)、0サイズに切り捨てます(可能な場合)。これはcat
始める前に起こります。 file1
将来の標準出力に設定されているため使用されますcat
。cat
file1
変える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
ため、「副作用」です。>file1
cat
このメカニズムを使用して、1つ以上のファイルを作成/切り捨てることができます。: >file1 >file2 …
ファイルを切り捨てようとします。:
動作せず、標準出力も使用しません。シェルが起動する前にリダイレクトを処理すると、作成と切り捨てが発生します:
。
これはsh
互換性のあるシェルで出力リダイレクトが機能する方法です。 MULTIOSオプションzsh
(参照この他の答え)は異なります。最初のリダイレクトは前の方向(端末など)を置き換えますが、連続リダイレクトは次へ追加方向。後ろでどのように起こるかは詳しく説明しません。私はあなたが観察した動作がsh
それぞれが処理されるという事実(または互換性のあるシェルから)から来ていることを指摘したいと思いました。>fileN
独立して、順番に。ただし、zsh
単一デバイスのように複数の出力をリダイレクトするモードがあります。