shuf file> fileコマンドは空のファイルを残しますが、同様のコマンドがそうでないのはなぜですか? [コピー]

shuf file> fileコマンドは空のファイルを残しますが、同様のコマンドがそうでないのはなぜですか? [コピー]

私はこれが他の質問と一種の重複であることを知っています(このソートコマンドが空のファイルを提供するのはなぜですか?)しかし、与えられた答えに基づいて質問を拡張したいと思います。

注文する

shuf example.txt > example.txt

シェルがファイルをミックスする前にカットしてブレンドする空のファイルのみを残すため、空のファイルが返されます。しかし、

cat example.txt | shuf > example.txt

予想通りスクランブルされたファイルが生成されます。

パイプメソッドは機能しますが、単純なリダイレクトが機能しないのはなぜですか?コマンドを実行する前にファイルが切り捨てられた場合、2番目の方法も空のファイルを残してはいけませんか?

答え1

問題は、ファイルの読み取りが開始さ> example.txtれる前にファイルの書き込みが開始されることです。shuf example.txtだからまだ出力がないので空でexample.txt、空のshufファイルを読み込み、shufこの場合には出力がないので最終結果は空になります。

他のコマンドでも同じ問題が発生する可能性があります。> example.txtファイルの読み取りを開始する前にファイルを終了できます。cat example.txtこれは、シェルがこれらの操作を実行する順序と、cat実際にファイルを開くのにかかる時間によって異なります。

これらの問題を完全に防ぐためにshuf example.txt > example.txt.shuf && mv example.txt.shuf example.txt

または一緒に行くことを選択することもできますshuf example.txt --output=example.txt

答え2

コンボその他のユーティリティ次のコマンドがありますsponge

   sponge  reads  standard input and writes it out to the specified file.
   Unlike a shell redirect, sponge soaks up all its input before  opening
   the output file. This allows constricting pipelines that read from and
   write to the same file.

このようにして、次のことができます。

shuf example.txt | sponge example.txt

残念ながら、moreutilsパッケージにはutilというツールもありますがparallel、これはgnuの並列よりはるかに便利ではありません。parallelmoreutils インストールを削除しました。)

答え3

君は運が良くて走れるだけだよ

cat example.txt | shuf > example.txt

example.txtこのコマンドのように空ではありません。

shuf example.txt > example.txt

リダイレクトは、コマンドを実行し、同時にパイプラインコンポーネントを実行する前にシェルで実行されます。

-o/オプションを使用するのが--output最善の解決策である可能性がありますが、shuf(非常に少し)リスクを負う場合は、処理されたファイルを読み取る前に切り捨てることを防ぐための異なる方法があります。

shuf example.txt | (sleep 1;rm example.txt;cat > example.txt)

提案してくれたOleに感謝します。この方法はより簡単で高速です。

(rm example.txt; shuf > example.txt) < example.txt

答え4

ExモードでVimを使用できます。

ex -sc '%!shuf' -cx example.txt
  1. %すべての行を選択

  2. !コマンドの実行

  3. x保存して閉じる

関連情報