Бинарный diff / patch для больших файлов на Linux?


13

У меня есть два образа раздела (A и B), и я хочу использовать их для создания патча, который я могу применить к A на другом компьютере, чтобы получить новый образ B, не затопляя сеть. У меня есть следующие требования:

  • работает на Linux
  • может создавать различия
  • можно использовать diffs для исправления файлов
  • может обрабатывать двоичные файлы
  • может обрабатывать большие файлы (несколько сотен ГБ должно работать)
  • взаимодействие с пользователем не требуется (только консольное приложение)
  • в идеале, должен иметь возможность чтения / записи в каналы (чтобы я мог передать в него из сжатого gzip файла и записать в один)

Существует ли что-то подобное?


Я нажал клавишу Enter слишком быстро при запуске щедрости. Вот текст, который я хотел добавить:
Basj

Ответ с примером, rdiffкоторый легко воспроизвести, был бы полезен для использования в будущем. Пример: Допустим , file1и file2два одинаковых файлов 1 Гб каждый. 1) Как вычислить rdiff? 2) Как сохранить этот rdiff в patchфайл? 3) Как применить этот patchфайл file1для восстановления file2?
Basj

Ответы:


13

Вероятно, вам стоит взглянуть на инструменты, связанные с rsync: rdiff и rdiff-backup . Команда rdiffпозволяет вам создать файл патча и применить его к другому файлу.

Команда rdiff-backupиспользует этот подход для работы с целыми каталогами, но я предполагаю, что вы работаете с однофайловыми образами дисков, поэтому rdiffбудет использовать именно их.


1
Что означает «подпись» и «дельта» для rdiff? Страница руководства не говорит.
Тор Клингберг

1
Чтобы ответить на мой собственный вопрос, создание дельты с помощью rdiff - это двухэтапный процесс. Сначала создайте файл подписи из старого файла, затем используйте подпись и новый файл для создания дельты. Они могут быть запущены вместе сrdiff signature oldfile | rdiff delta - newfile deltafile
Тор Клингберг

1
@TorKlingberg Не могли бы вы опубликовать новый ответ с примером? Допустим, file1и file2есть два одинаковых файла по 1 ГБ каждый. 1) Как рассчитать разницу? 2) Как сохранить этот diff в файл патча? 3) Как применить этот файл патча file1для восстановления file2?
Basj

7

xdelta может делать все, что вы хотите. Справедливое предупреждение, однако, если ваши изображения не очень похожи, вы можете получить очень большой патч, потому что xdelta использует половину определенного буфера памяти для поиска различий. Более подробная информация доступна на вики-странице TuningMemoryBudget . Увеличение размера буфера может немного помочь.

bsdiff - это еще один вариант, но он очень требователен к оперативной памяти и совершенно не подходит ни для какого размера диска.

bsdiff довольно жаждет памяти. Это требует max(17*n,9*n+m)+O(1)байтов памяти, где nразмер старого файла и mразмер нового файла. bspatch требует n+m+O(1)байтов.


3

Канонический ответ

Что касается статьи rdiff , librsync 2.0.1 хорошо подходит для пояснения функциональности команды, поэтому я сослался на это ниже, чтобы сохранить содержимое этого ответа, если ничего больше.

Важно попытаться понять три шага по обновлению файла rdiff : подпись , дельта и патч, о которых говорилось на справочной странице rdiff . Я также нашел rdiffполезный скрипт команды на GitHub, на который я буду ссылаться и цитировать.

По существу ...

  1. With a "starting" or base file [file1] and you create a signature file from it
    • Это обычно намного меньше, чем сам файл base / original
  2. С файлом подписи вы сравниваете его с другим файлом [ file2], похожим на ваш базовый файл, но другим ( например, недавно обновленным ), и создаете дельта-файл, содержащий только различия между этими двумя файлами.
  3. Используйте «только различия» или дельта-файл и сравните его с вашим базовым файлом [ file1], чтобы сгенерировать новый файл, содержащий изменения из другого файла [ file2], соответствующего двум.

Быстрые команды (за rdiff-example.sh)

rdiff signature file1 signature-file            ## signature base file1
rdiff delta signature-file file2 delta-file     ## delta differences file2
rdiff patch file1 delta-file gen-file           ## compare delta to file1 to create matching file2

rdiff-example.sh

# $ rdiff --help
# Usage: rdiff [OPTIONS] signature [BASIS [SIGNATURE]]
#              [OPTIONS] delta SIGNATURE [NEWFILE [DELTA]]
#              [OPTIONS] patch BASIS [DELTA [NEWFILE]]

# Options:
#   -v, --verbose             Trace internal processing
#   -V, --version             Show program version
#   -?, --help                Show this help message
#   -s, --statistics          Show performance statistics
# Delta-encoding options:
#   -b, --block-size=BYTES    Signature block size
#   -S, --sum-size=BYTES      Set signature strength
#       --paranoia            Verify all rolling checksums
# IO options:
#   -I, --input-size=BYTES    Input buffer size
#   -O, --output-size=BYTES   Output buffer size

# create signature for old file
rdiff signature old-file signature-file
# create delta using signature file and new file
rdiff delta signature-file new-file delta-file
# generate new file using old file and delta
rdiff patch old-file delta-file gen-file
# test
diff -s gen-file new-file
# Files gen-file and new-file are identical

Введение

rdiff - это программа для вычисления и применения сетевых дельт. Дельта rdiff - это дельта между двоичными файлами, описывающая, как базовый (или старый) файл может быть автоматически отредактирован для создания файла результата (или нового).

В отличие от большинства программ diff, librsync не требует доступа к обоим файлам при вычислении diff. Вычисление дельты требует только короткой «подписи» старого файла и полного содержимого нового файла. Подпись содержит контрольные суммы для блоков старого файла. Используя эти контрольные суммы, rdiff находит совпадающие блоки в новом файле, а затем вычисляет дельту.

Дельты rdiff обычно менее компактны, а также производятся медленнее, чем xdelt или обычные текстовые различия. Если возможно, чтобы при вычислении дельты присутствовали как старые, так и новые файлы, xdelta обычно создает файл намного меньшего размера. Если сравниваемые файлы представляют собой простой текст, тогда GNU diff обычно является лучшим выбором, так как различия могут просматриваться людьми и применяться как неточные совпадения.

rdiff вступает в свои права, когда не удобно, чтобы оба файла присутствовали одновременно. Одним из примеров этого является то, что два файла находятся на разных компьютерах, и вы хотите передать только различия. Другим примером является случай, когда один из файлов был перемещен на архивный или резервный носитель, оставив только свою подпись.

Символически

signature(basis-file) -> sig-file

delta(sig-file, new-file) -> delta-file

patch(basis-file, delta-file) -> recreated-file

Используйте шаблоны

Типичным применением алгоритма rsync является передача файла A2 с компьютера A на компьютер B, который имеет аналогичный файл A1. Это можно сделать следующим образом:

  1. B генерирует rdiff-сигнатуру A1. Назовите это S1. B отправляет подпись A. (подпись обычно намного меньше, чем файл, который она описывает.)
  2. A вычисляет дельту rdiff между S1 и A2. Назовите эту дельту D. A отправляет дельту B.
  3. B применяет дельту для воссоздания A2. В случаях, когда A1 и A2 содержат серии идентичных байтов, rdiff должен дать значительную экономию места.

источник


1
Большое спасибо!
Basj

1

JDIFF - это программа, которая выводит различия между двумя (двоичными) файлами.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.