ファイルの重複を調べるプログラムをPHPで書く

重複したファイルの名前をSQLiteに保存する。

ファイル名: find_duplicated_files.php
array_shift($argv);
$dirs = $argv;

$db = new SQLite3('./duplicated_files.db');
$db->exec("CREATE TABLE IF NOT EXISTS fingerprint (name VARCHAR(255), md5 CHAR(32), PRIMARY KEY(name))");
$db->exec("CREATE INDEX IF NOT EXISTS md5index on fingerprint(md5)");

if (count($dirs)>0) {

 $fingerprints = array();

 foreach ($dirs as $dir) {
  $files = explode("\n",`find "$dir"`);
  foreach ($files as $file) {
   $name = "$dir/$file";
   while (preg_match("|/\./|",$name)) $name = preg_replace("|/\./|",'/',$name);
   if (is_file($name)) $fingerprints[md5(@file_get_contents($name))][] = $name;
  }
 }

 foreach ($fingerprints as $md5 => $names) {
  if (count($names)>1) {
   foreach ($names as $name) {
    $name = str_replace("'","''",$name);
    $db->exec("INSERT OR REPLACE INTO fingerprint VALUES ('$name','$md5')");
   }
  }
 }

}

$q = $db->query("SELECT * FROM fingerprint");
while ($a=$q->fetchArray(SQLITE3_ASSOC)) echo $a['md5']."\t".$a['name']."\n";
MD5を使ってファイルのフィンガープリントを得て、フィンガープリントが一致したら同じファイルとした。
心配ならばフィンガープリントにファイルサイズを追加すればいい。

使い方はコマンドラインで
php find_duplicated_files.php DIR [DIR1 [DIR2 ...]]
と入力する。
複数のディレクトリを対象にするときはディレクトリを列記する。

ディレクトリを指定せずに
php find_duplicated_files.php
と入力すれば、取得済みのデータを表示する。
2013/02/13 23:25
タグ