ファイル記述子をエコーするとファイルが上書きされますか?

ファイル記述子をエコーするとファイルが上書きされますか?

ファイル記述子に書き込もうとしたときに何が起こっているのか理解できませんか?元の内容を上書きしたようですが?これが予想される動作ですか?

以下の例では、これを複製しました。

$ echo "The quick brown fox ..." > example.txt  
$ echo "The quick brown fox ..." >> example.txt
$ cat example.txt
The quick brown fox ...  
The quick brown fox ...
$ exec 88<>example.txt
$ cat example.txt
The quick brown fox ...  
The quick brown fox ...
$ echo "jumped" >&88  
$ cat example.txt
jumped  
ck brown fox ...  
The quick brown fox ...
$ echo "jumped" >&88  
$ cat example.txt
jumped  
jumped  
n fox ...  
The quick brown fox ...

答え1

ディスクリプタ88で読み出しが行われていないため、現在のナビゲーション位置は「0」であり、その時点で書き込みが行われる。

これとは対照的に、この前にファイルを読み取ると追加の操作が発生します。

bash-4.2$ cat <&88
The quick brown fox ...
The quick brown fox ...

bash-4.2$ echo hello >&88

bash-4.2$ cat example.txt 
The quick brown fox ...
The quick brown fox ...
hello

bash-4.2$ echo more >&88

bash-4.2$ cat example.txt 
The quick brown fox ...
The quick brown fox ...
hello
more

答え2

@Zoonoseが正しく指摘したように、各ファイルディスクリプタは、関連付けられたファイル内の独自の読み書きカーソル位置を持ちます。たとえば、リダイレクトを使用すると、<>シェルまたはプログラム(たとえば)を介してファイルを開くことができますcat

ただし、「ファイル記述子」と考える数字はカーネルの実際のファイル記述子への参照に過ぎず、単一のプロセス内またはプロセス間にファイル記述子に対して複数のこれらの参照番号があるのは完全に正常です。

したがって、ターミナルウィンドウを開くか、sshを介してログインすると、シェルプロセスはfd#0、fd#1、およびfd#2で接続されているターミナルで開いている単一のファイル記述子で始まります。パイプやリダイレクトを使用しない限り、シェルで開始されたすべてのプロセスはデフォルトでこれらのプロセスを継承します。

リダイレクトは>>ファイル記述子をO_APPEND書き込み用に表示します。それfiledescriptor はカーソルを無視し、ファイルの終わりに移動します。

リダイレクト>のため、ターゲットファイルは一度だけ切り捨てられます。今後すべての書き込みが完了しました。したがって、後で何を書いても通常ファイルの末尾に空白を入力してください。

ファイルの書き込みいいえ独自に切り捨てが発生します。必要に応じてファイルの末尾を増やして、現在の場所にあるものを置き換えます。

これにより、somecmd >&88somecmdの標準出力(fd#1)が現在のシェルのfd#88とファイル記述子を共有します。これはO_APPEND、オプションがある場合はそのオプションを共有することを意味します。それに慣れるもう一度切ります。これはワンタイムです。

この場合に見えるのは何もないということです。追加を使用すると、切り捨てられ>&88(fd#88はopenとして使用されないため>>)、既存のデータを上書きできます。

関連情報