forループの一部として同じファイルに書き込むと、空のファイルが生成されます。

forループの一部として同じファイルに書き込むと、空のファイルが生成されます。

特定のパターンに一致する複数のファイルにいくつかのテキストを追加するコマンドを作成しています。

for file in $(find . -name "*.txt"); do sed "1s/^/hello/" $file; done 

stdout別のファイル(たとえば)に書き込むと、すべてが計画"$file.bak"どおりに進みますが、コマンドを使用して同じファイルに書き換えようとすると、ファイルの内容が消去されます。

for file in $(find . -name "*.txt");do sed "1s/^/hello/" $file > $file; done

私はこの動作が驚くべきことだと思います。なぜこれが起こるのかを概念的に説明できる人はいますか?私は同じ効果bashでmacOSでこれを試しました。zsh

(私はsed -i ""正しい場所に書くことを知っていますが、それを書く前に結果を別のコマンドにパイプしたいと思います。)

ベストアンサー1

概念的な驚きはこの声明にあります。

しかし、同じファイルにコマンドを書き換えようとすると

使用すると、書き換えるためにファイルを開くのcmd file > fileではなくcmd、シェル自体を開きます。これが見つかったときにシェルが最初にすることは、書き込みモード> fileで場所0でファイルを開き(したがってファイルが切り捨てられ)、stdoutをファイルにリダイレクトすることです。したがってcmd、読み始める瞬間はfileすでに空です。

または、より正式には次のようになります。

  • cmdShell は実行する新しいプロセスを分岐します。
  • 新しいプロセス(まだ実行中のシェルコード)がfile位置0に書き込むために開きます(したがって切り捨てられます)。
  • 新しいプロセスの実行は、cmd実際には現在のプロセス内で新しいバイナリを起動します。
  • cmdランタイム標準出力は以下を指します。file
  • cmd読むために開いていますfileが、今は空です。

一方、sed -i '1s/^/hello/' file別々に管理されたファイルを使用する場合sed(技術的にはバックグラウンドで一時ファイルを生成します。)

おすすめ記事