tr stdoutをファイル[冗長]にリダイレクトする

tr stdoutをファイル[冗長]にリダイレクトする

重複の可能性:
iconvに入力ファイルを変換された出力に置き換えさせるにはどうすればよいですか?
上書きせずにLinuxで同じファイルを読み書きできますか?

$ cat test.txt 
This is a test file.
$ tr 'a' 'z' < test.txt 
This is z test file.
$ tr 'a' 'z' < test.txt > test.txt
$ cat test.txt
$ 

trがtest.txtに何も出力しないような理由は何ですか?私が見つけたこのスレッドしかし、何が起こっているのか、そして問題を解決する方法をよく理解していません。

(そして私がsedを使わない理由は、改行文字を別の文字に置き換えたいからですが、sedが1行単位で動作することはできないと思いますか?)

答え1

問題は、同じファイルから同時に読み書きすることです。

シェルは最初に空のファイルを生成する(つまり、ファイルを切り捨てる)出力リダイレクトを設定します。その後、入力リダイレクトを設定し、tr空のファイルから読み込みます。

次の一時ファイルを使用して問題を解決できます。

$ tr 'a' 'z' < test.txt > temp.txt && mv temp.txt test.txt

答え2

あるファイルから別のファイルに同時にリダイレクトすることはできません。少なくともそのような場合ではありません。問題は、シェルがリダイレクトを部分的に設定すると、ファイルが切り捨てられることです。だからtrはファイルから読み取ろうとしますが、空です。

ディストリビューションにこの問題を解決するプログラムをmoreutils含むパッケージがある場合は機能します。spongetr 'a' 'z' < test.txt | sponge test.txt

それ以外の場合は、出力を一時ファイルに書き込み、それを使用して元のmvファイルを上書きする必要があります。

関連情報