本文へジャンプ

GIDEON STAFF BLOG

ファイルのオーバーライド

通常のパイプ動作するフィルタコマンドでは 元ファイルを直接オーバライドできない。
例えば sort (1) の -o オプションの様に 元ファイルのオーバライド指定ができる (この動作をスポンジ動作というらしい)もの以外での処理について。

一番簡単で誰でも思いつくのが一時ファイルを利用するやりかた。

$ command < foo.dat > foo.new 
$ mv foo.new foo.dat
	
この方法だと command の実行中に割込が発生したりすると 一時ファイルが残ってしまい美しくない。

$ cat foo.dat | ( sleep 1; command > foo.dat)
	
この方法だと sleep (1) の時間がうっとおしく、 データ量や command の速度などによって失敗する場合もありうる。

$ (rm foo.dat; command > foo.dat) < foo.dat
	
若干判りづらいのだがこれで確実に成功する。
先行する rm (1) は必須である。 rm (1) がない場合は外側のシェルが '<' により O_RDONLYopen (2) するファイルと 内側のシェルが '>' により O_RDONLY|O_TRUNCopen (2) するファイルの inode が等しいので、 OS は同一ファイルと見做し command の標準入力は O_TRUC により truncate されたファイルとなってしまう。
対して rm (1) がある場合は、 外側のシェルが O_RDONLYopen (2) するファイルと、 内側のシェルが O_RDONLY|O_TRUNCopen (2) するファイルの inode が異なるので、 OS はそれぞれを違うファイルと見なすためである。