web-dev-qa-db-ja.com

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

ファイル記述子に書き込もうとするとどうなるか理解できません。元のコンテンツを上書きしているようです?これは予想される動作ですか?

以下の例でこれを複製しました:

$ 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 ...
7
Zoonose

ディスクリプター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
11
Stephen Harris

@Zoonoseが正しく指摘しているように、各ファイル記述子には、接続先のファイル内に独自の読み取り/書き込みカーソル位置があります。また、<>などのリダイレクトを使用するときにシェルによって、またはcatなどのプログラムによってファイルを開くことができます。

しかし、「ファイル記述子」と考える番号は、カーネル内の実際のファイル記述子への参照に過ぎず、1つのファイル記述子が単一のプロセス内またはプロセス間でそのような参照番号を複数持つことは完全に正常です。

したがって、ターミナルウィンドウを開く(またはsshでログインする)ときは、ターミナルに開いている単一のファイル記述子から始め、シェルプロセスでfd#0、fd#1、fd#2として接続します。シェルで始まるプロセスは、パイプまたはリダイレクトを使用した場合を除いて、デフォルトでこれらを継承します。

リダイレクト>>は、ファイル記述子にO_APPENDのフラグを立てます。これにより、書き込みがthat filedescriptorによって行われ、カーソルは無視され、ファイルの末尾に移動します。

リダイレクト>により、ターゲットファイルは1回だけ切り捨てられますbeforeすべての書き込みが行われます。したがって、その後の書き込みは通常がファイルの終わりを過ぎて空のスペースに入ります。

ファイルへの書き込みはnot自体が切り捨てを引き起こします。現在の位置にあるものは何でも置き換えるだけで、必要に応じてファイルの終わりを拡張します。

somecmd >&88を指定すると、somecmdのstdout(fd#1)がファイル記述子を現在のシェルのfd#88と共有することに注意してください。つまり、O_APPENDオプションが存在する場合はそれを共有します。 しない再度切り捨てられます。それは一度きりのものです。

この場合、>&88を使用してfd#88が開かれなかったため、>>を使用しても切り捨てが発生しないため、複数のプロセスからの書き込みをインターリーブできます。

4
Martin