Question Comment comparer des fichiers binaires sous Linux?


Je dois comparer deux fichiers binaires et obtenir la sortie sous la forme

<hexoffice-fichier> <hex-fichier-octet> <hex-octet fichier>

pour chaque octet différent. Donc si file1.bin est

  00 90 00 11

sous forme binaire et file2.bin est

  00 91 00 10

Je veux obtenir quelque chose comme

  00000001 90 91
  00000003 11 10

Quelle est la manière la plus simple d'atteindre cet objectif? Outil standard? Un outil tiers?

(Remarque: cmp -l devrait être tué avec le feu, il utilise un système décimal pour les décalages et octal pour les octets.)


253
2018-03-29 15:28


origine


vous cherchez essentiellement "diff binaire". je peux imaginer un one-liner avec od... - quack quixote
@quack quixote: Qu'est-ce qui est moche dans un one-liner? ;) - Bobby
xdelta.org fonctionne assez bien. Peut-être faudrait-il y jeter un coup d’œil. - thatjuan


Réponses:


Cela affichera le décalage et les octets en hexadécimal:

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'

Ou faire $1-1 pour que le premier offset imprimé commence à 0.

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1-1, strtonum(0$2), strtonum(0$3)}'

Malheureusement, strtonum() est spécifique à GAWK, donc pour d'autres versions de awk-par exemple, mawk-vous devrez utiliser une fonction de conversion octale à décimale. Par exemple,

cmp -l file1.bin file2.bin | mawk 'function oct2dec(oct,     dec) {for (i = 1; i <= length(oct); i++) {dec *= 8; dec += substr(oct, i, 1)}; return dec} {printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)}'

Brisé pour la lisibilité:

cmp -l file1.bin file2.bin |
    mawk 'function oct2dec(oct,    dec) {
              for (i = 1; i <= length(oct); i++) {
                  dec *= 8;
                  dec += substr(oct, i, 1)
              };
              return dec
          }
          {
              printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)
          }'

143
2018-03-29 16:30



Malheureusement, cela me donne awk: line 2: function strtonum never defined erreurs sur Ubuntu 12.04. Implémentation spécifique AWK peut-être? - gertvdijk
@gertvdijk: strtonum est spécifique à GAWK. Je crois qu'Ubuntu utilisait auparavant GAWK par défaut, mais a changé mawk. Dans tous les cas, GAWK peut être installé et défini sur la valeur par défaut (voir aussi man update-alternatives). Voir ma réponse mise à jour pour une solution qui ne nécessite pas strtonum. - Dennis Williamson
J'ai ajouté l'impression du caractère original et l'ai mise dans le menu mc, j'ai dû doubler les signes%: cmp -l %d/%f %D/%f | gawk '{printf "%%08X %%02X %%02X %%c %%c\n", $1-1, strtonum(0$2), strtonum(0$3), strtonum(0$2), strtonum(0$3)}' - 18446744073709551615


Comme ~ charlatan souligné:

 % xxd b1 > b1.hex
 % xxd b2 > b2.hex

Et alors

 % diff b1.hex b2.hex

ou

 % vimdiff b1.hex b2.hex

137
2018-03-29 16:07



Dans Bash: diff <(xxd b1) <(xxd b2) mais le format de sortie de ceci (ou du vôtre) est loin de ce que l’OP a demandé. - Dennis Williamson
avec vimdiff c'est, il va colorer les octets dans les lignes où les deux fichiers diffèrent - akira
Cela a bien fonctionné pour moi (avec opendiff sur OS X au lieu de vimdiff) - la vue par défaut xxd fournit le moteur de comparaison sur piste comparant octet par octet. Avec hex simple (brut) simplement en colonne avec fold, diff essaierait de plier / grouper des choses aléatoires dans les fichiers que je comparais. - natevw
Cette commande ne fonctionne pas bien pour la suppression des ajouts d’octets, car chaque ligne qui suit sera mal alignée et vue comme modifiée par diff. La solution consiste à mettre 1 octet par ligne et à supprimer la colonne d’adresse proposée par John Lawrence Aspden et moi. - Ciro Santilli 新疆改造中心 六四事件 法轮功
Votre réponse est parfaite pour les petits fichiers, mais pas pour les gros. - peterh


Essayer diff dans la combinaison suivante de substitution de processus zsh / bash et colordiff en CLI:

diff -y <(xxd foo1.bin) <(xxd foo2.bin) | colordiff

Où:

  • -y vous montre les différences côte à côte (facultatif)
  • xxd est un outil CLI pour créer une sortie hexdump du fichier binaire
  • colordiff colorisera diff sortie (installation via: sudo apt-get install colordiff)
  • ajouter -W200 à diff pour une production plus large

Astuces:

  • si les fichiers sont trop gros, ajoutez une limite (par ex. -l1000) pour chaque xxd

Sortie de l'échantillon:

binary file output in terminal - diff -y <(xxd foo1.bin) <(xxd foo2.bin) | colordiff


57
2017-09-05 21:14



La commande peut être simplifiée comme colordiff -y <(xxd foo1.bin) <(xxd foo2.bin). - golem
Si vous n'avez pas colordiff, cela fera la même chose sans couleurs: diff -y <(xxd foo1.bin) <(xxd foo2.bin) - Rock Lee
Si vous voulez simplement savoir si les deux fichiers sont identiques, vous pouvez utiliser le -q ou --brief switch, qui affichera uniquement la sortie lorsque les fichiers diffèrent. - Stefan van den Akker
créer une fonction xxddiff pour cela avec: xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; ) - rubo77
génial! encore, diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim -  fera un bon travail enoug - ribamar


Il y a un outil appelé DHEX qui peut faire le travail, et il y a un autre outil appelé VBinDiff.

Pour une approche strictement en ligne de commande, essayez JDIFF.


48
2018-03-29 15:41



DHEX est génial de comparer les binaires est ce que vous voulez faire. Alimentez-le en deux fichiers et vous accédez directement à une vue comparative, en mettant l’accent sur les différences, avec la possibilité de passer facilement à la différence suivante. Il est également capable de travailler avec de gros terminaux, ce qui est très utile sur les moniteurs à écran large. - Marcin
Je préfère VBinDiff. DHEX utilise le processeur même au repos, je pense qu'il est en train de redessiner tout le temps ou quelque chose. VBinDiff ne fonctionne pas avec les terminaux larges. Mais les adresses deviennent bizarres avec des terminaux larges, puisque vous avez plus de 16 octets par ligne. - Janus Troelsen
vbindiff nous permet en fait d'éditer le fichier, thx! - Aquarius Power
Les fichiers compressés @DanielBeauyat seront complètement différents après avoir rencontré le premier octet différent. La sortie ne sera probablement pas utile. - Mark Ransom
@ 1111161171159459134 jdiff fait partie d'une "suite" de programmes pour synchroniser et corriger les différences trouvées par jdiff. Mais, comme l’a dit Mark Ransom, ce ne serait généralement pas judicieux pour les fichiers compressés; l'exception est les formats compressés "synchronisables" (comme ceux produits par gzip --rsyncable), dans lesquels les petites différences dans les fichiers non compressés devraient avoir un effet limité sur le fichier compressé. - hmijail


Méthode qui fonctionne pour l'ajout / suppression d'octets

diff <(od -An -tx1 -w1 -v file1) \
     <(od -An -tx1 -w1 -v file2)

Générez un scénario de test avec une seule suppression de l'octet 64:

for i in `seq 128`; do printf "%02x" "$i"; done | xxd -r -p > file1
for i in `seq 128`; do if [ "$i" -ne 64 ]; then printf "%02x" $i; fi; done | xxd -r -p > file2

Sortie:

64d63
<  40

Si vous souhaitez également voir la version ASCII du caractère:

bdiff() (
  f() (
    od -An -tx1c -w1 -v "$1" | paste -d '' - -
  )
  diff <(f "$1") <(f "$2")
)

bdiff file1 file2

Sortie:

64d63
<   40   @

Testé sur Ubuntu 16.04.

je préfère od plus de xxd car:

  • il est POSIX, xxd n'est pas (vient avec Vim)
  • a la -An supprimer la colonne d'adresse sans awk.

Explication de commande:

  • -An supprime la colonne d'adresse. Ceci est important sinon toutes les lignes différeraient après un ajout / suppression d'octet.
  • -w1 met un octet par ligne, de sorte que diff puisse le consommer. Il est crucial d'avoir un octet par ligne, sinon chaque ligne après une suppression deviendrait déphasée et différerait. Malheureusement, ce n'est pas POSIX, mais présent dans GNU.
  • -tx1 est la représentation que vous voulez, passez à une valeur possible, tant que vous conservez 1 octet par ligne.
  • -v empêche l'abréviation de répétition astérisque * ce qui pourrait interférer avec le diff
  • paste -d '' - - rejoint toutes les deux lignes. Nous en avons besoin parce que l'hexagone et l'ASCII vont dans des lignes adjacentes séparées. Pris à partir de: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • nous utilisons des parenthèses () définir bdiff au lieu de {} limiter la portée de la fonction interne f, voir également: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Voir également:


25
2018-04-04 20:31





Réponse courte

vimdiff <(xxd -c1 -p first.bin) <(xxd -c1 -p second.bin)

Lorsque vous utilisez hexdumps et text diff pour comparer des fichiers binaires, en particulier xxd, les ajouts et les retraits d’octets deviennent des changements d’adressage qui peuvent rendre la lecture difficile. Cette méthode indique à xxd de ne pas générer d'adresses et de ne sortir qu'un octet par ligne, ce qui montre exactement quels octets ont été modifiés, ajoutés ou supprimés. Vous pouvez trouver les adresses plus tard en recherchant les séquences d’octets intéressantes dans un hexdump plus "normal" (sortie de xxd first.bin).


12
2018-04-22 12:10



(Bien sûr, on peut utiliser diff au lieu de vimdiff.) - VasyaNovikov


Je recommande hexdump pour vider les fichiers binaires au format textuel et kdiff3 pour l'affichage diff.

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex

10
2018-06-12 07:46



Même ici à bash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin) sans besoin de créer des fichiers myfile1.hex et myfile2.hex. - Hastur