`>`と `>>`はどのように機能しますか?


9

revファイルにパイプしてからパイプしようとしたcat > same_fileが、空のファイルになっていた。

試しrev file.txt | cat > file2.txt && mv file.txt file2.txt;てみましたが、うまくいきました。

でもrev file.txt | cat >> file.txt;働いた。

しかし、私が試しrev file.txt | cat > file.txtたとき、それは失敗しました。


次のように省略することもできcatますrev file.txt > file2.txt && mv file2.txt file.txt。これはの余分な使用法ですcat。それを省略することで、余分なプロセスを生成する余裕ができます。
matega

回答:


19

この場合、リダイレクトの両方の方法(>と>>)の間で把握する必要がある基本的なことは次のとおりです。

>

指し示された情報をリダイレクトして上書きします。これは、パイプ "|"を介して情報を受信して​​いるときに発生します

>>

指示された情報にリダイレクトして連結します。これは、パイプ "|"を介して情報を受信して​​いるときに発生します

どちらの場合も、ファイルが存在しない場合は、代わりに作成されます。「>>」でのみ、同じファイルで再度実行すると情報が連結されます。">"を使用すると、最初の実行時に行ったすべてのことを単純に上書きします。

しかし、ここでは出力ファイルと同じ入力ファイルを使用する場合の取り決めがあります。その特定の場合、「>」を使用すると、出力ファイルが「上書き」するため、「入力」部分が解析する必要のある情報が削除されます。だから:

rev file.txt | cat > file.txt

「スローモーション解説」で実際に起こっているのは:

  1. revの内容を反転file.txtしてパイプに送信する準備をします
  2. revがパイプに情報を送信している間、パイプはそれを直接にストリーミングしcatます。
  3. cat情報を受信している間、file.txt設定された情報に自動的に適用されます。
  4. すべてが同時に起こっているので、ここでのキーワードは「while」です。この部分をより深く理解するには、以下のEmilによる優れたコメントを参照してください。
  5. catrevファイル全体をパイプするのを待ちません。これは、情報の最初の部分が到達する直前に開始されます。つまり、使用した記号に応じて、への接続が開かれfile.txtます。
  6. この場合、>>ではなく>を使用したので、シェルは出力ファイルを切り捨てます。つまり、新しい情報が届くのを待つ間に、シェルは開いて情報をクリアします。>>それはとの接続を開くだろうし、検出された最後の行に新しい情報を待ちます。file.txtfile.txt
  7. 情報はすでに>でクリアされfile.txtているので、新しい情報に備えてすべてを削除したので、それは機能して何も得られません。revcat

それで、なぜ上記を読んだ後に他の人が働くのですか?このため:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

ここでは、情報を別のファイルに送信しているcatにパイプしています。この場合、処理された入力ファイルfile.txtは出力ファイルと同じではありませんfile2.txt。その後、文字通り全体file2.txtfile.txtで上書きしているため、によって行われたすべてのプロセスcatが削除されました。基本的に行全体を単純化することができます。cp file.txt file2.txtこれはfile2.txt、最後にが失わrevれ、mvコマンドで上書きされるため、同じことをしているためです。

rev file.txt | cat >> file.txt

この場合、同じファイルに情報を連結しています。したがって、それはそのファイルへの接続を開くだけで、単一の>で見られるような情報は消去しません。最終結果は、元の情報と逆の情報になります。


5
ファイルは猫によって切り捨てられません。パイプライン内のコマンドが開始される前に、シェルによって切り捨てられます。
EmilJeřábek2015年

正解、説明しやすい言葉を探していました。OPがシェルとそれをすべて知っているかどうかをOPが認識していないかどうかを説明するのは少し難しいので。できるだけ「友好的」にしようとしています。
Luis Alvarado、2015年

1
まあ、それがシェルによって行われることは本当に重要ではありませんが、あなたが提示するタイミングは間違っています。切り捨てはステップ6では行われませんが、ステップ0 rev file.txt | cat --bogus-option > file.txtでは猫がファイルを開こうとしない場合でも、ファイルが切り捨てられます。
EmilJeřábek、2015年

@EmilJeřábekあなたは正しいです。それでも、コマンドだけで段階的に進めれば、動作がわからないユーザーにとっては簡単になります。また、あなたの例はまだ同じファイルに情報を送信しているので、bashはその行全体を読み取り、出力を確認し、それでも開いて切り捨てます。エラーは単にstderrがstdoutに出力することです。
Luis Alvarado、2015年

4
moreutilsも参照してください。ツールの素晴らしいコレクション(パッケージリポジトリからとして入手可能moreutils)にはsponge、入力ファイルを上書きするユースケース用に特別に設計されたツールが含まれています。たとえば、rev file.txt >file2.txt && mv file2.txt file.txt回避策はになりますrev file.txt | sponge file.txt。これは、名前がすでにある場合でも正しく機能しfile2.txtます。
Daniel Wagner

9

シェルはリダイレクトを検出すると、関連するコマンドを実行する前に、まず関連ファイルを開きます。したがって、あなたがするとき:

foo file.txt | bar > file.txt

へのリダイレクトfile.txtにより、実行 に切り捨てられてfoo読み取ることができますfile.txt。余談ですが、これができない理由です。

sed 'blah' file.txt > file.txt

そして、なぜsedインプレース編集オプションがあります。

最後に、次のことを行います。

.. | cat > file.txt

ある猫の無駄な使用は、あなたがから読み取るしようとしている場合は特にそう、file.txt上の早いです。

ファイルを元の場所に戻す場合、ショートカットはありませんsedまたはawkインプレース編集でトリックを使用できる場合があります。


3

>出力を別の何かに送るリダイレクタ(オペレータ)です
(次のコマンドの入力、プリンタなど)。

あなたの場合、出力はファイルfile.txtに送られます。このファイルがすでに存在する場合は、作成されない場合は上書きされます。

>>追加演算子です。file.txt既に存在する場合、出力はファイルの最後に追加されます。ファイルが存在しない場合は作成され、出力は>(リダイレクター)と同じように新しいファイルに書き込まれます。


OPはこれを理解したようです。混乱は、同じファイルが>and >>演算子の両側にあることに起因するようです。
bzlm 2015年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.