これ:
echo 'some text' > file.txt
cat file.txt > file.txt
明らかに私に空のファイルを与えるようです。
しかし、私を驚かせたのは次のとおりです。
cat2 () {
cat "$@" > tmp.txt
cat tmp.txt
return $?
}
echo 'some text' > file.txt
cat2 file.txt > file.txt
.tmp.txt
file.txt
この方法も通じません! :
echo 'some text' > file.txt
cat file.txt | cat2 > file.txt
ファイルが消去され続けるのはなぜですか?
答え1
注文
cat2 file.txt > file.txt
新しい空きスペースを作りますfile.txt
今後関数を呼び出しますcat2
。
そのため、実行時にファイルcat2
は空になり、空のcat
出力が発生します。
作業の順序を破るのに役立つ場合、あなたがしたことは次のとおりです。
- コンテンツを含むfile.txtファイルを作成します。
- 新しい空のファイルfile.txtを作成します。
- cat2を実行し、file.txtとして出力します。
これは、リダイレクト演算子がcat2
実行前に発生するためです。
答え2
tr
次の設定は機能します(作業例として使用されます)。
{ 'rm' -f File.txt && tr '[:lower:]' '[:upper:]' > File.txt; } < File.txt
入力リダイレクトは、< File.txt
ブロック内のエントリを実行する前に、ファイルを中括弧内のステートメントに標準入力として割り当てます。
ファイルに開かれたファイル記述子があるため、ブロック内でファイルを削除しても内容は削除されません。オプションrm
の使用など、可能なエイリアシングの状況を避けるために引用符を付けました-i
。
出力リダイレクトは、元のファイルと同じ名前の新しい出力ファイル(inode)を生成します。終了すると、tr
新しいファイルが閉じます。
最後に、入力リダイレクトが完了し、ディレクトリまたはファイル記述子を介した接続がなくなり、そのリソースが解放されます。
Stéphane Chazelasの優れた意見に基づいて編集されました。
(a)すべてのプロンプトとエラーを防ぐためのオプションが必要rm
です。-f
(b)tr
ロケールに依存しない文字クラスを使用する必要があります。
(c) 新しい File.txt は、他の inode 番号、作成時間、および可能であれば所有権、権限、acl、またはその他の拡張属性など、以前の File.txt とは無関係です。また、シンボリックリンクを通常のファイルに置き換え、ハードリンクを分離して元のデータを別のパス名に保ちます。