Disons que jai un fichier de 4 Go abc sur mon ordinateur local. Je lai téléchargé sur un serveur distant via SFTP, cela a pris quelques heures.
Maintenant, jai légèrement modifié le fichier (probablement 50 Mo maximum, mais pas doctets consécutifs dans ce fichier) localement, et lai enregistré dans abc2. Jai également conservé le fichier dorigine abc sur mon ordinateur local.
Comment calculer un diff binaire de abc et abc2?
Applications:
-
Je ne pouvais envoyer quun fichier
patch(probablement 100 Mo maximum) à le serveur distant, au lieu de télécharger à nouveau le fichierabc2(cela prendrait encore quelques heures!), et recréezabc2sur le serveur distant serveur deabcetpatchuniquement. -
Localement, au lieu de gaspiller 8 Go pour sauvegarder à la fois
abcetabc2, je nai pu enregistrer queabc+patch, donc cela prendrait < 4100 Mo seulement.
Comment faire?
PS: pour le texte, je sais diff, mais ici je « cherche quelque chose qui pourrait fonctionner pour nimporte quel format binaire brut, ce pourrait être des fichiers zip ou des exécutables ou même dautres types de fichiers.
PS2: Si possible, je ne veux pas utiliser rsync; Je sais quil peut répliquer les changements entre 2 ordinateurs de manière efficace (sans renvoyer des données qui nont pas changé), mais ici je veux vraiment avoir un fichier patch, reproductible plus tard si Jai à la fois abc et patch.
Réponse
Pour la deuxième application / problème, jutiliserais un programme de sauvegarde de déduplication comme restic ou borgbackup, plutôt que dessayer pour suivre manuellement les « patches » ou les diffs. Le programme de sauvegarde restic vous permet de sauvegarder des répertoires de plusieurs machines vers le même référentiel de sauvegarde, en dédupliquant les données de sauvegarde à la fois parmi les fragments de fichiers dune machine individuelle ainsi quentre les machines. (Je nai aucune expérience utilisateur avec borgbackup, donc je ne peux rien dire à propos de ce programme.)
Calcul et stockage dun diff de abc et abc2 peuvent être créés avec rsync.
Ceci est un exemple avec abc et abc2 étant de 153 Mo. Le fichier abc2 a été modifié en écrasant le premiers 2,3 Mo du fichier avec dautres données:
$ ls -lh total 626208 -rw-r--r-- 1 kk wheel 153M Feb 3 16:55 abc -rw-r--r-- 1 kk wheel 153M Feb 3 17:02 abc2
Nous créons patch pour transformer abc en abc2 et lappeler abc-diff:
$ rsync --only-write-batch=abc-diff abc2 abc
$ ls -lh total 631026 -rw-r--r-- 1 kk wheel 153M Feb 3 16:55 abc -rw------- 1 kk wheel 2.3M Feb 3 17:03 abc-diff -rwx------ 1 kk wheel 38B Feb 3 17:03 abc-diff.sh -rw-r--r-- 1 kk wheel 153M Feb 3 17:02 abc2
Le fichier généré abc-diff est le diff réel (votre « fichier de patch »), tandis que abc-diff.sh estun court script shell que rsync crée pour vous:
$ cat abc-diff.sh rsync --read-batch=abc-diff ${1:-abc}
Ce script modifie abc pour quil devienne identique à abc2, étant donné le fichier abc-diff:
$ md5sum abc abc2 be00efe0a7a7d3b793e70e466cbc53c6 abc 3decbde2d3a87f3d954ccee9d60f249b abc2 $ sh abc-diff.sh $ md5sum abc abc2 3decbde2d3a87f3d954ccee9d60f249b abc 3decbde2d3a87f3d954ccee9d60f249b abc2
Le fichier abc-diff pourrait maintenant être transféré partout où vous avez abc. Avec la commande rsync --read-batch=abc-diff abc, vous appliqueriez le correctif au fichier abc, en transformant son contenu pour quil soit le même que celui de abc2 sur le système sur lequel vous avez créé la différence.
Réappliquer le patch une deuxième fois semble sûr. Il ny a pas de message derreur et le contenu du fichier ne change pas (la somme de contrôle MD5 ne change pas).
Notez quà moins que vous ne créiez un « patch inversé » explicite, il ny a aucun moyen dannuler facilement lapplication du patch.
Jai également testé lécriture de la modification de 2,3 Mo à un autre endroit dans les données abc2, un peu plus loin (à environ 50 Mo), ainsi quau début. Le « patch » généré faisait 4,6 Mo de large, ce qui suggère que seuls les bits modifiés ont été stockés dans le patch.
Commentaires
- Merci beaucoup @Kusalananda, ‘ est super! PS:
rsync --read-batch=abc-diff ${1:-abc}(script .sh généré automatiquement) a donnéremote destination is not allowed with --read-batchrsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2], maisrsync --read-batch=abc-diff abca fonctionné avec succès.Quelle est la différence entre ces deux commandes similaires? - 2/2 Existe-t-il un moyen de prendre
abcen entrée, appliquer le correctifdiff-abcavec--read-batchmais sans modifierabc» sur place « , mais plutôt une sortie dans un nouveau fichierabc3? (si possible tout avecrsync, sans tuyauterie, pour que cela fonctionne facilement sous Linux ainsi que Windows qui a égalementrsync.exedisponible) - @Basj Les commandes feraient des choses différentes si
$1avait une valeur.${1:-abc}signifie que » utiliser le premier paramètre de position ($1) sauf sil ‘ est vide ou indéfini. Dans le cas où il ‘ est vide ou non défini, utilisezabcà la place « . Je ‘ m en supposant que$1avait une valeur lorsque vous lavez essayé, peut-être quelque chose quil a interprété comme un adresse de destination distante. - @Basj Je ‘ Je ne suis pas tout à fait sûr que cela soit possible, mais je ‘ ll jetez un œil demain après votre sommeil.
- Merci pour votre réponse sur
${1:-abc}. Cela a probablement échoué parce que je lai essayé sous Windows (je ‘ m en utilisant rsync à la fois sur Linux pour mon serveur distant et Windows localement). Mais cela ‘ est parfait puisquersync --read-batch=abc-diff abcfonctionne 🙂
Réponse
Comment calculer un diff binaire de abc et abc2?
En utilisant bsdiff / bspatch ou xdelta et autres.
$ bsdiff older newer patch.bin # patch.bin is created [...] $ bspatch older newer patch.bin # newer is created
Cependant, ces avertissements des pages de manuel sont à noter:
-
bsdiffutilise une mémoire égale à 17 fois la taille de oldfile et nécessite une taille de jeu de travail minimale absolue égale à 8 fois la taille de oldfile . -
bspatchutilise une mémoire égale à la taille de oldfile plus la taille de newfile , mais peut tolérer un très petit ensemble de travail sans perte dramatique de performances.
Commentaires
Réponse
Avez-vous essayé de forcer simplement diff pour traiter les fichiers comme du texte:
diff -ua abc abc2
Comme expliqué ici .
-
-uaffiche NUM (par défaut 3) lignes de contexte unifié -
-atraiter tous les fichiers comme du texte
Cela devrait vous apporter un correctif. Linconvénient de ceci est que les « lignes » pourraient être assez longues et cela pourrait gonfler le patch.
Commentaires
- Oups, oui, vous navez pas ‘ t veulent réellement le
n. Je ‘ suis intéressé de savoir si cela fonctionne comme je ‘ ne sais pas combien de temps le » lignes » le seront. - Merci pour votre commentaire! Jai créé deux fichiers de 256 Mo très similaires
abcetabc2. Ensuite, jai essayédiff -ua abc abc2 > patch, puis jai copiéabcversabc3et jai essayé de récupérerabc2grâce àabc3etpatch:patch abc3 < patch, mais cela na pas fonctionné: à la fin,abc3ne faisait que 1 Ko au lieu de 256 Mo. Une idée? - Hmmm, je ne sais pas ce qui sest passé. Je lai juste fait sur ma machine et cela a mieux fonctionné que ce à quoi je mattendais.Jai pris un fichier 382M qui était des entiers aléatoires écrits en binaire dans un fichier. Jai changé 3 octets et jai fait le diff et le patch et cela a fonctionné. Les fichiers résultants étaient égaux à md5sum.
- Si un gros fichier na pas doctet
0x0a, cest-à-dire une nouvelle ligne, ou très peu, je suppose que cela ne serait pas ‘ t fonctionne si bien, il serait intéressant de tester. - Oh bien sûr. Vous pouvez faire une estimation éclairée sur un binaire avec
wc -lqui recherchera des sauts de ligne et, daprès mon expérience, sexécute très rapidement. Je mattendrais à ce que sur un binaire arbitraire, cela fonctionne plutôt bien. Par exemple, sur ma machine, jai trouvé un mp4 de 252 millions de pixels contenant 1,2 million de » lignes » et un 59M.debqui avait environ 230 Ko, donc une moyenne de » lignes » de moins de 220 octets et 258 octets respectivement. Je ne ‘ pas voir pourquoi ces fichiers seraient si différents des autres, mais vous pourriez certainement être malchanceux. En pratique, je soupçonne que cela fonctionnerait plutôt bien et sinon, ‘ reste un hack amusant.
Réponse
Utilisez xdelta , il a été créé exactement pour ce type dutilisations. Basé sur VCDIFF (RFC 3284) dans les dernières versions.
Commentaires
- Le lien ne fonctionne pas (y a-t-il une autre URL?). Pourriez-vous également ajouter un exemple en quelques lignes pour montrer comment: 1) calculer le fichier diff
patch, et 2) restaurerabc2, donné uniquementabcetpatch? - Désolé, URL fixe
- Merci @vonbrand . Auriez-vous un tel exemple?
Réponse
Compléments à dautres réponses selon mes tests:
Avec diff
Jai créé deux fichiers de 256 Mo très similaires abc et abc2. Ensuite, créons le fichier diff:
diff -ua abc abc2 > abc-abc2.diff
Essayons maintenant de récupérer abc2 grâce au fichier dorigine abc et abc-abc2.diff:
cp abc abc3 patch abc3 < abc-abc2.diff
ou
cp abc abc3 patch abc3 -i abc-abc2.diff
ou
patch abc -i abc-abc2.diff -o abc3
Cela fonctionne sous Linux. Jai également essayé sur Windows (patch.exe et diff.exe sont également disponibles), mais pour une raison inconnue, il a échoué: le fichier abc3 produit ne fait que 1 Ko au lieu de 256 Mo (I » Je mettrai à jour cette réponse plus tard ici).
Avec rsync
Comme détaillé dans la réponse acceptée, cela fonctionne:
rsync --only-write-batch=abc-abc2-diff abc2 abc cp abc abc3 rsync --read-batch=abc-abc2-diff abc3
Avec rdiff
Comme détaillé dans ceci réponse , cest aussi une solution:
rdiff signature abc abc-signature rdiff delta abc-signature abc2 abc-abc2-delta rdiff patch abc abc-abc2-delta abc3
Testé également sous Windows avec rdiff.exe de ici et ça marche.
Commentaires
- Je ‘ je suppose que le correctif a échoué sous Windows car il lisait le fichier dentrée en mode » text » qui signale la fin du fichier lorsquil rencontre un CONTROL -Z (octet 0x18) dans le fichier dentrée. Il sagit dun mode hérité des premiers jours DOS où le répertoire nenregistrait pas la longueur de le fichier et donc la longueur du fichier a été calculée en fonction du nombre de secteurs de 512 octets. Si vous pouvez dire à
patchdouvrir le fichier en mode binaire, il ne devrait pas ‘ avoir cette erreur.
bsdiff uses memory equal to 17 times the size of oldfiledonc cela ne fonctionnera ‘ que pour des fichiers de 4 Go (au moins sur ma machine de 8 Go de RAM).mydiff abc abc2 > patchfileetmypatch abc patchfile > abc3) quelle que soit la taille. De plus, si je découpe en morceaux de 128 Mo, que se passe-t-il si le premier 1 Go deabc== le dernier 1 Go (de fin) deabc2? Lorsque nous ‘ compareronsabc-first128mbavecabc2-first128mb, aucune correspondance ne sera trouvée, donc il pourrait ne pas être efficace?