答えは「たぶんそうですが、それはファイルシステムのタイプとタイミングに依存します」です。
これら3つの例のいずれも、偶然を除き、old_fileまたはexisting_fileの物理データブロックを上書きしません。
mv new_file old_file
。これにより、old_fileのリンクが解除されます。old_fileへの追加のハードリンクがある場合、それらの残りのリンクではブロックは変更されません。それ以外の場合、ブロックは一般に(ファイルシステムのタイプによって異なります)フリーリストに配置されます。次に、mv
コピーが必要な場合(ディレクトリエントリを移動するだけではなく)、新しいブロックがmv
書き込みとして割り当てられます。
これらの新しく割り当てられたブロックは、ちょうど解放されたものと同じ場合とそうでない場合があります。UFSなどのファイルシステムでは、可能であれば、ファイルが作成されたディレクトリと同じシリンダーグループからブロックが割り当てられます。そのため、ディレクトリからファイルをリンク解除し、同じディレクトリにファイルを作成すると再利用される可能性があります(上書き)ちょうど解放された同じブロックのいくつか。これが、ファイルを誤って削除する人への標準的なアドバイスが、誰かがファイル回復を試みることができるまで、ディレクトリツリー内のファイルに(できればファイルシステム全体ではなく)新しいデータを書き込まないことです。
cp new_file old_file
以下を実行します(strace
システムコールの表示に使用できます)。
open( "old_file"、O_WRONLY | O_TRUNC)= 4
O_TRUNCフラグは、mv
上記と同様に、すべてのデータブロックを解放します。また、上記のように、それらは一般にフリーリストに追加され、cp
コマンドによって行われる後続の書き込みで再利用される場合とされない場合があります。
vi existing_file
。場合はvi
、実際にあるvim
、:x
コマンドは次の処理を行います。
unlink( "existing_file〜")= -1 ENOENT(そのようなファイルまたはディレクトリはありません)
rename( "existing_file"、 "existing_file〜")= 0
open( "existing_file"、O_WRONLY | O_CREAT | O_TRUNC、0664)= 3
そのため、古いデータも削除されません。データはバックアップファイルに保存されます。
FreeBSDでは、vi
doesは、上記open("existing_file",O_WRONLY|O_CREAT|O_TRUNC, 0664)
と同じセマンティクスを持ちcp
ます。
特別なプログラムなしでデータの一部またはすべてを回復できます。必要なのはgrep
、とdd
、そしてrawデバイスへのアクセスだけです。
小さなテキストファイルの場合、リンク先の質問の@Steven Dからgrep
の回答にある1つのコマンドが最も簡単な方法です。
grep -i -a -B100 -A100 'text in the deleted file' /dev/sda1
しかし、複数の非連続ブロックにある可能性のある大きなファイルの場合、私はこれを行います:
grep -a -b "text in the deleted file" /dev/sda1
13813610612:this is some text in the deleted file
これにより、一致する行のバイト単位のオフセットが得られます。次の一連のdd
コマンドを実行します。
dd if=/dev/sda1 count=1 skip=$(expr 13813610612 / 512)
また、そのブロックの前後のいくつかのブロックを読みたいでしょう。UFSでは、ファイルブロックは通常8KBで、通常はかなり連続して割り当てられます。単一ファイルのブロックは、他のファイルまたは空き領域の8KBブロックと交互にインターリーブされます。UFS上のファイルのテールは、最大7個の1KBフラグメントであり、連続している場合と連続していない場合があります。
もちろん、データを圧縮または暗号化するファイルシステムでは、回復はそれほど簡単ではありません。
実際、Unixには、既存のファイルのデータブロックを上書きするユーティリティはほとんどありません。頭に浮かぶのはdd conv=notrunc
。もう1つはshred
です。