標準入力を吸収するためにこの関数を使用できないのはなぜですか?

標準入力を吸収するためにこの関数を使用できないのはなぜですか?

これ:

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.txtfile.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 とは無関係です。また、シンボリックリンクを通常のファイルに置き換え、ハードリンクを分離して元のデータを別のパス名に保ちます。

関連情報