Comment comparer des parties de fichiers par hachage?

19

J'ai un fichier téléchargé avec succès et un autre téléchargement échoué (seulement les 100 premiers Mo d'un gros fichier) que je soupçonne être le même fichier.

Pour vérifier cela, je voudrais vérifier leurs hachages, mais comme je n'ai qu'une partie du fichier téléchargé sans succès, je veux seulement hacher les premiers mégaoctets.

Comment puis-je faire cela?

Le système d'exploitation serait Windows, mais j'ai installé cygwin et MinGW.

péché
la source
1
La comparaison efficace d'un fichier sur un ordinateur local avec un autre fichier sur un ordinateur distant est un élément clé de rsync , qui compare des parties des fichiers avec une fonction de hachage spéciale.
David Cary
@DavidCary Dans mon cas, je n'ai pas d'accès shell à l'ordinateur distant, mais merci pour l'astuce, je vais lire la page de manuel
péché

Réponses:

56

Créer des hachages pour comparer des fichiers est logique si vous comparez un fichier à plusieurs ou lorsque vous comparez plusieurs fichiers les uns aux autres.

Cela n'a aucun sens lorsque vous comparez deux fichiers une seule fois: l'effort pour calculer les hachages est au moins aussi élevé que de parcourir les fichiers et de les comparer directement.

Un outil de comparaison de fichiers efficace est cmp:

cmp --bytes $((100 * 1024 * 1024)) file1 file2 && echo "File fragments are identical"

Vous pouvez également le combiner avec ddpour comparer des parties arbitraires (pas nécessairement depuis le début) de deux fichiers, par exemple:

cmp \
    <(dd if=file1 bs=100M count=1 skip=1 2>/dev/null) \
    <(dd if=file2 bs=100M count=1 skip=1 2>/dev/null) \
&& echo "File fragments are identical"
Konrad Rudolph
la source
6
Remarque: la création de hachages pour comparer des fichiers est également judicieuse si vous souhaitez éviter de lire deux fichiers en même temps.
Kamil Maciorowski
1
@KamilMaciorowski Oui, c'est vrai. Mais cette méthode sera généralement plus rapide que la comparaison des hachages dans le cas des paires.
Konrad Rudolph
8
C'est la solution à emporter. cmpest à 99,99% certain d'être déjà installé si vous avez en bashcours d' exécution, et il fait le travail. En effet, cmp -n 131072 one.zip two.zip fera également le travail. Moins de caractères à taper et exécution la plus rapide. Calculer un hachage est absurde. Il nécessite la lecture de l'intégralité du fichier de 100 Mo , plus une partie de 100 Mo du fichier complet, ce qui est inutile. S'il s'agit de fichiers zip et qu'ils sont différents, il y aura une différence dans les quelques centaines de premiers octets. Readahead fournit cependant 128 Ko par défaut, vous pouvez donc également comparer 128 Ko (même coût que la comparaison avec 1 octet).
Damon
19
L' --bytesoption ne fait que compliquer la tâche. Exécutez simplement cmpsans cette option et il vous montrera le premier octet qui diffère entre les fichiers. Si tous les octets sont identiques, cela s'affichera EOFsur le fichier le plus court. Cela vous donnera plus d'informations que votre exemple - combien d'octets sont corrects.
pabouk
2
Si vous avez GNU cmp(et, je pense que presque tout le monde en a), vous pouvez utiliser des arguments --ignore-initialet --bytesau lieu de compliquer les choses avec des invocations de dd.
Christopher Schultz
12

Je suis désolé, je ne peux pas vraiment essayer ça, mais ça fonctionnera

dd if=yourfile.zip of=first100mb1.dat bs=100M count=1
dd if=yourotherfile.zip of=first100mb2.dat bs=100M count=1

Cela vous permettra d'obtenir les 100 premiers mégaoctets des deux fichiers.

Maintenant, récupérez les hachages:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

Vous pouvez également l'exécuter directement:

dd if=yourfile.zip bs=100M count=1 | sha256sum 
dd if=yourotherfile.zip bs=100M count=1 | sha256sum 
davidbaumann
la source
1
Existe-t-il un moyen de canaliser dd d'une manière ou d'une autre dans sha256sum sans le fichier intermédiaire?
péché
1
J'ai ajouté un autre moyen selon votre demande
davidbaumann
8
Pourquoi créer les hachages? C'est beaucoup moins efficace que de comparer directement les fragments de fichiers (en utilisant cmp).
Konrad Rudolph
Dans votre exemple de code du milieu, vous dites first100mb1.dat deux fois. Voulez-vous dire first100mb 2 .dat pour le second?
doppelgreener
@KonradRudolph, "Pourquoi créer les hachages?" Votre solution (en utilisant cmp) est sans aucun doute gagnante. Mais cette façon de résoudre le problème (en utilisant des hachages) a également le droit d'exister tant qu'elle résout le problème (:
VL-80
7

Tout le monde semble suivre la voie Unix / Linux avec cela, mais simplement comparer 2 fichiers peut facilement être fait avec les commandes standard de Windows:
FC /B file file2

FC est présent sur toutes les versions de Windows NT jamais réalisées. Et (si je me souviens bien) était également présent sous DOS.
C'est un peu lent, mais cela n'a pas d'importance pour une utilisation unique.

Tonny
la source
6

Vous pouvez simplement comparer directement les fichiers, avec un programme de comparaison binaire / hexadécimal comme vbindiff. Il compare rapidement les fichiers jusqu'à 4 Go sur Linux et Windows.

Ressemble à quelque chose comme ça, seulement avec la différence surlignée en rouge (1B vs 1C):

one                                       
0000 0000: 30 5C 72 A7 1B 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....
0000 0020:
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080: 
0000 0090: 
0000 00A0: 

two        
0000 0000: 30 5C 72 A7 1C 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....               
0000 0020: 
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080:
0000 0090:                                
0000 00A0:             
┌──────────────────────────────────────────────────────────────────────────────┐
Arrow keys move  F find      RET next difference  ESC quit  T move top        
C ASCII/EBCDIC   E edit file   G goto position      Q quit  B move bottom     
└──────────────────────────────────────────────────────────────────────────────┘ 
Xen2050
la source
Dans mon cas, les fichiers sont des archives zip, donc pas de texte significatif là-dedans. La comparaison de la valeur de hachage doit être plus rapide et moins sujette aux erreurs.
péché
2
Si vous voulez dire du texte ASCII, cela n'a pas d'importance. vbindiff(et Konrad cmp) compare les données binaires, octet par octet. En fait, les valeurs sont beaucoup plus susceptibles de subir des collisions
Xen2050
* Signifiait "En fait, les valeurs HASH sont beaucoup plus susceptibles de subir des collisions" dans le commentaire ci-dessus, raté le h!
Xen2050
0

Je sais que cela dit pour Bash, mais OP indique également qu'ils ont Windows. Pour tous ceux qui veulent / nécessitent une solution Windows, il existe un programme appelé HxD qui est un éditeur hexadécimal qui peut comparer deux fichiers. Si les fichiers sont de tailles différentes, il dira si les pièces disponibles sont les mêmes. Et si besoin est, il est capable d'exécuter des sommes de contrôle pour tout ce qui est actuellement sélectionné. Il est gratuit et peut être téléchargé à partir du site Web HxD . Je n'ai aucun lien avec les auteurs, je l'utilise depuis des années.

Blerg
la source
0

cmp vous indiquera quand deux fichiers sont identiques jusqu'à la longueur du fichier plus petit:

$ dd if=/dev/random bs=8192 count=8192 > a
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.514571 secs (130417197 bytes/sec)
$ cp a b
$ dd if=/dev/random bs=8192 count=8192 >> b 
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.512228 secs (131013601 bytes/sec)
$ cmp a b
cmp: EOF on a

cmp vous indique que la comparaison a rencontré un EOF sur le fichier a avant de détecter une différence entre les deux fichiers.

Jim L.
la source
Bon point. Si vous ne l'avez pas vu, c'est ce que pabouk a déjà commenté sur la réponse acceptée.
péché