2010-09-25 18 views
2

Je voudrais écrire un script qui traverse une arborescence de fichiers, calcule un hachage pour chaque fichier, et insère le hachage dans une table SQL avec le chemin du fichier, de sorte que je puisse alors interroger et rechercher des fichiers identiques. Quelle serait la fonction de hachage recommandée ou une commande comme outil pour créer des hachages qui sont extrêmement peu susceptibles d'être identiques pour différents fichiers? Merci Bmysql/fichier hash question

Répondre

0

vous pouvez utiliser md5 ou SHA1

function process_dir($path) { 

    if ($handle = opendir($path)) { 
     while (false !== ($file = readdir($handle))) { 
     if ($file != "." && $file != "..") { 
      if (is_dir($path . "/" . $file)) { 
       process_dir($path . "/" . $file); 
      } else { 
       //you can change md5 to sh1 
       // you can put that hash into database 
       $hash = md5(file_get_contents($path . "/" . $file)); 
      } 
     } 
     } 
     closedir($handle); 
    } 
} 

si vous travailler dans le changement de Windows barres obliques à barres obliques inversées.

1

Je travaille sur ce problème depuis trop longtemps. Je suis sur mon troisième (et je l'espère finale) réécrire.

De manière générale, je recommande SHA1 car il n'a pas de collisions connues (alors que les collisions MD5 can be found in minutes), et SHA1 n'a pas tendance à être un goulot d'étranglement lorsqu'on travaille avec des disques durs. Si vous êtes obsédé par l'exécution rapide de votre programme en présence d'un disque SSD, vous pouvez soit utiliser MD5, soit perdre des jours et des jours de votre temps à déterminer comment paralléliser l'opération. Dans tous les cas,   pas   paralléliser   hacher jusqu'à ce que votre programme fasse tout ce que vous avez besoin de faire.

En outre, je recommande d'utiliser sqlite3. Lorsque j'ai créé mes hachages de fichiers dans une base de données PostgreSQL, les insertions de base de données étaient un véritable goulot d'étranglement. Certes, j'aurais pu essayer d'utiliser COPY (j'oublie si je l'ai fait ou non), et je suppose que cela aurait été raisonnablement rapide.

Si vous utilisez sqlite3 et exécutez les insertions dans un bloc BEGIN/COMMIT, vous recherchez probablement environ 10000 insertions par seconde en présence d'index. Cependant, ce que vous pouvez faire avec la base de données résultante en vaut la peine. Je l'ai fait avec environ 750000 fichiers (85 Go). L'opération de hachage INSERT et SHA1 complète a pris moins d'une heure et a créé un fichier sqlite3 de 140 Mo. Cependant, ma requête pour trouver des fichiers en double et les trier par ID prend moins de 20 secondes à courir. En résumé, l'utilisation d'une base de données est bonne, mais notez l'en-tête d'insertion. SHA1 est plus sûr que MD5, mais prend environ 2,5 fois plus de puissance CPU. Cependant, les E/S tendent à être le goulot d'étranglement (le CPU est une seconde proche), donc l'utilisation de MD5 au lieu de SHA1 ne vous fera pas gagner beaucoup de temps.

+0

À quelle distance êtes-vous avec votre outil? J'ai été à la recherche d'un outil simple qui fait cela depuis des lustres mais qui n'a rien trouvé en ligne au-delà des outils de shareware "comparez deux répertoires". – b20000

+0

Mon programme est déjà capable de charger des informations d'arborescence de fichiers dans une base de données et de hacher des fichiers; ça marche fabuleusement. Je travaille actuellement sur le problème du remplacement des fichiers en double avec des liens durs. Notez que mon programme ne fonctionnera probablement que sous Linux et d'autres systèmes de type Unix car il est lié à la structure de statistiques remplie par ['lstat()'] (http://linux.die.net/man/2/lstat) fonction. –

+0

En outre, il n'a absolument aucune interface pour le moment; vous devrez coller dans le chemin que vous voulez scanner, et pour des opérations plus compliquées, apprenez à travailler avec du code Haskell. –

0

Voici une solution que j'ai trouvée. Je ne l'ai pas tout cela en PHP mais il serait assez facile à faire si vous voulez:

$fh = popen('find /home/admin -type f | xargs sha1sum', 'r'); 
$files = array(); 
while ($line = fgets($fh)) { 
    list($hash,$file) = explode(' ', trim($line)); 

    $files[$hash][] = $file; 
} 
$dupes = array_filter($files, function($a) { return count($a) > 1; }); 

Je me rends compte que je ne l'ai pas utilisé les bases de données ici. Combien de fichiers allez-vous indexer? Avez-vous besoin de mettre ces données dans une base de données, puis recherchez les dupes là-bas?

+0

merci - j'ai écrit un script dans le même temps qui utilise une DB sqllite – b20000