回答:
ファイルシステムの境界を越えてファイルを移動しない限り、操作は安全です。これは、»移動«が実際に行われるメカニズムによるものです。
mv
同じファイルシステム上のファイルの場合、ファイルは実際には変更されず、ファイルシステムのエントリのみが変更されます。
$ mv foo bar
実際に次のようなことをします
$ ln foo bar
$ rm foo
これにより、名前が付けられたファイル(実際にはファイルシステムエントリが指すiノード)のハードリンク(2番目のディレクトリエントリ)が作成され、エントリが削除されます。現在、を削除するときに、のiノードを指す2番目のファイルシステムエントリがあります。古いエントリを削除しても、実際にはiノードに属するブロックは削除されません。foo
bar
foo
foo
foo
foo
開いているファイルハンドルがファイルシステムエントリではなくファイルのiノードを指しているため、プログラムはとにかくファイルに追加します。
注:プログラムが書き込みと書き込みの間にファイルを閉じて再度開くと、古いファイルシステムエントリで新しいファイルが作成されることになります。
ファイルシステム間の移動:
ファイルシステムの境界を越えてファイルを移動すると、事態がgetいものになります。以来、この場合、あなたは、あなたのファイルの一貫性維持持つことを保証することができませんでしたmv
、実際に希望
または
$ cp /path/to/foo /path/to/bar
$ rm /path/to/foo
それぞれ
$ touch /path/to/bar
$ cat < /path/to/foo > /path/to/bar
$ rm /path/to/foo
アプリケーションの書き込み中にコピーがファイルの終わりに到達するかどうかによっては、新しいファイルに半分の行しかない場合があります。
さらに、アプリケーションが古いファイルを閉じて再度開かない場合、削除されたように見えても、古いファイルへの書き込みを続けます。カーネルは開いているファイルを認識し、ファイルシステムエントリを削除しますが、アプリケーションが開いているファイルハンドルを閉じるまで、古いファイルのiノードと関連するブロックは削除されません。
file-system borders
ですか?
あなたはnode.jsを使用していると言うので、ファイルの名前を変更するためにfs.rename()
(またはfs.renameSync()
)を使用していると思います。このnode.jsメソッドは、 rename(2)システムコール、ファイル自体には一切触れず、ファイルシステムにリストされている名前を変更するだけです。
" rename()ファイルの名前を変更し、必要に応じてディレクトリ間で移動します。ファイルへの他のハードリンク(link(2)を使用して作成された)は影響を受けません。。oldpathのも影響を受けません。"
特に、上記で引用した最後の文に注意してください。これは、開いているファイル記述子(プログラムがファイルへの書き込みに使用するものなど)は、名前が変更された後も引き続き指し示します。したがって、ファイルへの書き込み中にファイル名を変更しても、データの損失や破損はありません。
Andreas Weiseが答えで指摘しているように、rename(2)システムコール(したがってfs.rename()
node.js内)はファイルシステムの境界を越えて機能しません。したがって、この方法でファイルを別のファイルシステムに移動しようとすると失敗します。
Unix mv
コマンドは、エラーを検出し、代わりにコンテンツを新しいファイルにコピーして元のファイルを削除することでファイルを移動することにより、この制限を隠そうとします。残念ながら、このようなファイルを移動することはありません、それが書き込まれている間、ファイルを移動した場合のリスクデータの損失を。したがって、同時に書き込まれる可能性のあるファイルの名前を安全に変更する場合は、使用しないでくださいmv
(少なくとも、新しいパスと古いパスが同じファイルシステム上にあることを絶対に確認する必要があります)。
rename()
システムコールがありませんでした。ので、元のバージョンはmv
実際にlink()
ハードリンクを作成するために呼び出し、その後unlink()
に元の名前を削除しました。rename()
これをカーネルに原子的に実装するために、FreeBSDに追加されました。