Posted by & filed under 未分類.


父親が撮り鉄で、WindowsのPCで大量の写真をUSB外付けディスクに保存して管理していたのだけれど、その親父がマルウェアに汚染され倒して遅くなったPCに根本的な解決策を施した。

Windows8.1のクリーンインストールという核スイッチはUSB外付けディスクでさえ初期化してしまうらしい。(たぶんリテラシのない親父がメニュー間違えただけだと思うけど)
Baiduやなんかで色々問題になっているけれど、パソコンが不調になったときに自分で対処できない人はフリーソフトやその類は使うべきでない。どんな仕込みが入っているかすぐにはわからないからだ。

ということで、綺麗にフォーマットされてしまった2TBのハードディスクを渡され、大量の画像ファイルの復旧をすることになった。

debianでも利用可能なntfs-toolsのundeleteコマンドを利用するも、ファイルシステム上で削除されたファイルしか検出できず、フォーマットされる前のものの復元はできなかった。

そこで検討したのは EaseUS datarecovery wizard と Finaldata 10

両者ともセクタスキャンが可能で、時間が許せば2TBを全部読み込んで可能性のあるファイルを見付けだしてくれる。両方とも試供版でどれくらい助かりそうかまでは確認することができた。いずれも売価は7000円前後。

前者のEaseUSは2TBを読み込む途中で不正終了するのでFinaldata10で復旧することに決め、12万枚もの画像を救出することができた。
ちなみに2TBのディスクをUSB2でスキャンすると150時間かかる。ちょっと遅すぎちゃうかなどとボヤきつつ毎晩進捗を見ていたが、80時間目くらいにオフになったディスプレイをスペースキーで復活させたところ、中断されてしまった(中止にフォーカスが当たっていた)。自分のせいやけどやはりWindowsは嫌いや。Finaldataにも中断された再開する機能を実装してもらいたい。もはや数時間で解決できるような問題は少ないんではないかと思う。

フォーマットされてしまうとファイル名などの情報が復旧されないため、なにがなんだかわからない状態になってしまう。ちなみに12万枚の内、かなりの枚数が複製によるものということも眺めてわかった。
ということで、ここからは重複除去をする方法、および取得可能なものについてはEXIFから情報を抽出して名称を付け替える処理を検討した。

処理はdebian上で行なった。Redhatなどでも問題なく実施できるはずだ。
毎度のことではあるが、この文章による障害や事故については保証しないので、参考にして作業する場合も自己の責任において実施していただきたい

1. 重複ファイルの検出

ロジックを作成するのも面倒なので、sha1sumでハッシュを作成し、重複するフィンガープリントのファイルをがさっと消してしまうことにした。
(/mnt/disk/restore にファイルがある想定)
ファイルのフィンガープリントを作成(対象件数が多過ぎるのでfindで実行する)
$ cd /mnt/disk/restore
$ find ./ -type f -exec sha1sum {} ; | sort > files.sum
$ less files.sum
0000d38fc76834f913908593cb5fad48c20662ce ./jpg/#259538616.JPG
0002e55243fbab6a766d93db65ad7eb7fa81b2ff ./jpg/#255201456.JPG
0003143aa02a2639069bd26ca912d70d27b79dcc ./jpg/#353345088.JPG
0004470e8587ed1acdd1c8c18c4bed5146da2d63 ./jpg/#612002424.JPG
0004470e8587ed1acdd1c8c18c4bed5146da2d63 ./jpg/#658702376.JPG
0004caf37836025c3e51da70cd95aa067f22531d ./jpg/#350668848.JPG
0005420f45557d92976f2db2dd35c3a0c7385faf ./jpg/#71054968.JPG
0005eb438ea950e4364f029db31a53a3f793eaef ./jpg/#208824752.JPG
フィンガープリントの文字列順にソートした状態で出力する。これで上の行と自分の行のフィンガープリントが同じであれば、重複していると見做せる。

$ awk -e 'BEGIN {H=0;} {if (H == $1) { printf("%s %sn", $2, F); } else { H = $1; F = $2 }}' files.sum > dups.list
$ less dups.list
./jpg/#658702376.JPG ./jpg/#612002424.JPG
./jpg/#208825160.JPG ./jpg/#208824752.JPG
./jpg/#237570712.JPG ./jpg/#129325576.JPG
./jpg/#177345584.JPG ./jpg/#113059880.JPG
./jpg/#180130104.JPG ./jpg/#113059880.JPG
./jpg/#212403320.JPG ./jpg/#113059880.JPG
./jpg/#608047712.JPG ./jpg/#113059880.JPG
./jpg/#303852336.JPG ./jpg/#113615624.JPG
./jpg/#39478832.JPG ./jpg/#113615624.JPG
./jpg/#651855912.JPG ./jpg/#113615624.JPG
右側は比較元のファイル。左側カラムを適当にカットしてxargsに喰わせる。
$ mkdir trash
$ cut -d' ' -f1 dups.list | xargs -I '{}' mv '{}' trash
ちなみに何が起こっているのか確認したい場合は、mvの前にechoを挿入してみよう。


$ ls -1 jpg | wc -l
82252

$ ls -1 trash | wc -l
41176
ねむくなったので、今日はここまで。

続きはこちら。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です