bash – `>>` でのリダイレクトは、ターゲットファイルがまだ存在しない場合に `>>` と同等か?

bash redirection sh

Bashやshのようなシェルを考えてみましょう。>>>の基本的な違いは、対象のファイルが存在する場合に現れます

  • >はファイルをサイズ0に切り捨ててから書き込みます
  • >>は切り捨てではなく、ファイルの最後に書き込む(追記する)

ファイルが存在しない場合は、サイズがゼロの状態で作成され、その後に書き込まれます。これはどちらの演算子にも当てはまります。対象となるファイルがまだ存在しない場合には、両演算子は同等に見えるかもしれません

本当にそうなのか?

  81  None  2018-07-23


ベストアンサー

tl;dr

いいえ、>>は本質的に「常にファイルの末尾をシークする」のに対し、>は最後に書き込まれた場所へのポインタを保持しています


Full answer

(注: 私のテストはすべて Debian GNU/Linux 9 で行われました).

Another difference

いいえ、等価ではありません。別の違いがあります。それは、対象となるファイルが以前に存在していたかどうかに関わらず、顕在化する可能性があります

それを観察するには、データを生成するプロセスを実行して、>>>でファイルにリダイレクトします(例: pv -L 10k /dev/urandom > blob)。それを実行して、ファイルのサイズを変更します (例: truncate)。> はオフセットを維持しているのに対し、>> は常に末尾に追加していることがわかります

  • ファイルをより小さいサイズに切り詰める場合(0サイズでも構いません)
    • >は気にしません、それは何事もなかったかのように所望のオフセットで書き込みます; オフセットを切り捨てた直後にファイルの終わりを超えている、これはファイルがその古いサイズを取り戻し、さらに成長する原因となります、欠落したデータは(可能であれば、疎な方法で)ゼロで埋められます;
    • >>は新しい端に追加され、ファイルはその切り捨てられたサイズから成長します
  • ファイルを拡大してみると
    • >は気にしません、何事もなかったかのように所望のオフセットで書き込みます; サイズを変更した直後にオフセットがファイルの内部のどこかにあります、これは、オフセットが新しい終わりに到達するまで、しばらくの間、ファイルの成長を停止させます、その後、ファイルは正常に成長します;
    • >>は新しい端に追加され、ファイルはその拡大されたサイズから成長します

もう一つの例は、データ生成プロセスが実行されていてファイルに書き込んでいるときに、(別の>>を使って)何か余分なものを追加することです。これはファイルを拡大するのと似ています

  • >での生成処理は、所望のオフセットで書き込みを行い、最終的には余分なデータを上書きします
  • >>での生成処理は、新しいデータをスキップして過去のデータを追加します(競合状態が発生する可能性があり、2つのストリームがインターリーブされる可能性がありますが、それでもデータは上書きされません)

Example

それは実際には重要ですか?そこにはこの質問があります

私は標準出力に多くの出力を生成するプロセスを実行しています。それをすべてファイルに送る [….] ログローテーションプログラムのようなものを使うことはできますか?

この解答は、このように動作するcopytruncateオプションを持つlogrotateであると述べています

コピーを作成した後、古いログファイルを移動させ、必要に応じて新しいログファイルを作成する代わりに、元のログファイルをその場で切り捨てます

上に書いたことによると、>でリダイレクトすると、切り捨てられたログがあっという間に大きくなってしまいます。スパースネスはその日を救うでしょう。それにもかかわらず、連続したログには完全に不要な先頭のゼロがどんどん入ってきます

しかし、logrotateがスパースネスを維持せずにコピーを作成した場合、これらの先頭のゼロは、コピーが作成されるたびに、より多くのディスクスペースを必要とすることになります。私はツールの動作を調査していませんが、(圧縮が有効になっていれば)その場でスパースネスや圧縮を行うことで十分にスマートになるかもしれません。それでも、ゼロはトラブルの原因になるだけかもしれませんし、せいぜい中立であるだけかもしれません

この場合、ターゲットファイルがまだ作成されようとしている場合でも、>の代わりに>>を使用することで、かなり良い結果が得られます


Performance

このように、2つの演算子は開始時だけでなく、後から見ても動作が異なります。これにより、何らかの(微妙な?今のところ、それを支持するか反証する意味のあるテスト結果はありませんが、一般的には両者の性能は同じだと自動的に決めつけてはいけないと思います

108  Kamil Maciorowski  2018-07-23


タイトルとURLをコピーしました