「同じパイプで同じファイルを読み書きしないように注意してください」

「同じパイプで同じファイルを読み書きしないように注意してください」

シェルチェックレポート:

echo -e "blah/blah\n$(cat "$tmpdir"/"$filename".jpdf)" > "$tmpdir"/"$filename".jpdf
                          ^-- SC2094: Make sure not to read and write the same file in the same pipeline.
                                                         ^-- SC2094: Make sure not to read and write the same file in the same pipeline.

blah/blahこのコマンドの目的は、ファイルの先頭に行を挿入することです"$tmpdir"/"$filename".jpdf

「同じパイプで同じファイルを読み書きしないでください」とはどういう意味ですか?

どうすればいいですか?

ありがとうございます。

答え1

他の回答で指摘したように、同じファイルを読み書きすると、ファイルが消去されるという警告が表示されます。その理由は、>入力が完了する前にファイルが切り捨てられるためです。

2つの選択肢があります。

  1. sponge梱包を取り外して使用してくださいmoreutilssponge次のコマンドにパイプする前に、入力が完全に消費されていることを確認してください。

    変える

    command "$file" > "$file"
    

    する

    command "$file" | sponge "$file"
    
  2. 出力を別のファイルにリダイレクトし、名前を変更します。

    このように

    command "$file" > "$file2" && mv "$file2" "$file"
    

特定の質問に関連してファイルに「何か、あまりにも」を追加すると、そのsedオプションがサポートされている場合に-i機能します。例えばGNU sed:

sed '1i\
blah/blah' -i "$file"

答え2

それは、最も文字通りの意味で言うことを正確に意味します。このコマンドが実際に行うことは、ファイルを上書きして1行だけ$tmpdir/$filename.jpdfエコーすることです。シェルはリダイレクトを確認し、ファイルを切り取り、書き込み用に開きます。その後、コマンドを実行して(新しい)コンテンツの作成を開始します。あなたがしなければならないのは、新しい内容を別のファイルに書き込んでから、2番目のコマンドで新しいファイルを古い名前にコピーすることです。

答え3

より簡単なコマンドラインを入力してみましょう。

cat file > file

ファイルにデータが含まれている場合は削除されます。以下を試してください。

$ echo "content of file" > file
$ cat file
content of file

$ cat file > file

$ cat file
                     # empty file.

シェルはコマンドを実行する前にリダイレクトを処理します。
処理中は書き込み切り捨て用に>file開きますfile
それ以降はファイルが空です。
このコマンドはcat空のファイルに対してcat操作を実行し、何も書きません。

関連情報