Как я могу проверить, равны ли два gzipped файла?

Я перемещаюсь между многими дистрибутивами Linux и версиями. Универсальный путь - который я беру в этих случаях:

Прочитайте init-сценарий - он часто получает одну руду больше конфигурационных файлов. Если init-сценарий не анализирует конфигурационного файла, можно изменить init-сценарий. Недостаток состоит в том, что обновление пакета, которому принадлежит init-сценарий, перезапишет Ваши изменения.

11
08.02.2013, 20:40
3 ответа

Ответ @deroberts является большим, хотя я хочу поделиться некоторой другой информацией, которую я нашел.

gzip-l-v

gzip-сжатые-файлы уже содержат хеш (не безопасный, хотя, посмотрите, что это ТАК отправляет):

$ echo something > foo
$ gzip foo
$ gzip -v -l foo.gz 
method  crc     date  time           compressed        uncompressed  ratio uncompressed_name
defla 18b1f736 Feb  8 22:34                  34                  10 -20.0% foo

Можно объединить CRC и несжатый размер для получения быстрого цифрового отпечатка:

gzip -v -l foo.gz | awk '{print $2, $7}'

cmp

Для проверки, равны ли два байта или нет, использовать cmp file1 file2. Теперь, gzipped файл имеет некоторый заголовок с данными и нижним колонтитулом (CRC плюс первоначальный размер) добавленный. Описание gzip формата показывает, что заголовок содержит время, когда файл был сжат и что имя файла является nul-завершенной строкой, которая добавляется после 10-байтового заголовка.

Так, предполагая, что имя файла является постоянным и та же команда (gzip "$name") используется, можно проверить, отличаются ли два файла при помощи cmp и пропуск первых байтов включая время:

cmp -i 8 file1 file2

Примечание: предположение, что те же опции сжатия важны, иначе команда, будет всегда сообщать о файле как отличающемся. Это происходит, потому что опции сжатия хранятся в заголовке и могут влиять на сжатые данные. cmp просто взгляды на необработанные байты и не интерпретируют его как gzip.

Если у Вас есть имена файлов той же длины, то Вы могли попытаться вычислить байты, которые будут пропущены после чтения имени файла. Когда имена файлов имеют другой размер, Вы могли работать cmp после пропуска байтов, как cmp <(cut -b9- file1) <(cut -b10- file2).

zcmp

Это - определенно лучший способ пойти, он сначала сжимает данные и начинает сравнивать байты с cmp (действительно, это - то, в чем выполняют zcmp (zdiff) сценарий оболочки).

Одно примечание, не бойтесь следующего примечания в странице руководства:

Когда оба файла должны быть несжатыми перед сравнением второе является несжатым к/tmp. Во всех других случаях zdiff и zcmp используют только канал.

Когда у Вас будет достаточно новый Bash, сжатие не будет использовать временный файл, просто канал. Или, как zdiff источник говорит:

# Reject Solaris 8's buggy /bin/bash 2.03.
7
27.01.2020, 19:58
  • 1
    Если байт 4 (FLG) 0 затем, имя файла не находится в заголовке, таким образом, Вы не должны волноваться о его длине. Кроме того, я нашел gzip -v -l сообщит время файла вместо MTIME, если четыре байта MTIME в заголовке будут нулем. Также отметьте, там ли MTIME, это обычно немного перед временем файла, потому что это когда запущенное сжатие. –  kitchin 08.02.2016, 07:25

Можно использовать zcmp или zdiff как mreithub предполагает в его комментарии (или команда Kevin, которая подобна). Они будут относительно неэффективны, поскольку они на самом деле распаковывают оба файла и затем выдают их к cmp или diff. Если Вы просто хотите ответить, "они то же", Вы хотите cmp, это будет намного быстрее.

Ваш подход с md5sum совершенно хорошо, но необходимо взять MD5 перед выполнением gzip. Затем сохраните его в файле вместе с получающимся .gz файл. Можно затем сравнить файл легко, прежде, чем сжать его. Если имя является тем же, md5sum -c сделает это для Вас.

$ mkdir "backup1"
$ cd backup1
$ echo "test" > backup-file
$ md5sum backup-file > backup-file.md5
$ gzip -9 backup-file

И следующее резервное копирование:

$ mkdir "backup2"
$ cd backup2
$ echo "test" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: OK

Таким образом, это не изменилось. OTOH, изменили его:

$ echo "different" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: FAILED
md5sum: WARNING: 1 computed checksum did NOT match

Если Вы передаете --quiet к нему он просто даст Вам код выхода. 0 для подобранного, не0 для отличавшегося.

MD5 довольно быстр, но не ослепительно так. MD4 (openssl md4 является лучшим, Вы входите в командную строку, я верю), приблизительно вдвое более быстро (ни это, ни MD5 не безопасны, но оба о, чем коллизия, стойкая, когда никто не пытается ниспровергать их). SHA-1 (sha1sum) более безопасно, но медленнее; SHA-256 (sha256sum) безопасно, но еще медленнее все еще. CRC32 должен быть много раз быстрее, но короче и таким образом будет иметь более случайные коллизии. Его также совершенно небезопасный.

7
27.01.2020, 19:58
  • 1
    zdiff кажется отходами, поскольку я просто хочу знать, изменился ли файл, не что. zcmp выглядит интересным, я попробую это. –  Lekensteyn 08.02.2013, 23:24

Сравнить два gzip файла, просто содержание, одна команда, нет diff, просто сравнение md5sum

$ diff -q <(zcat one.gz|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|md5sum|cut -f1 -d' ') \
    && echo same || echo not_same

Можно также "отфильтровать" для соответствующих различий,

$ diff -q <(zcat one.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
   && echo same || echo not_same

При сценариях я рекомендовал бы функцию фильтра (не протестированный, просто пример),

do_filter_sum() {
  zcat $1 | grep -v '^-- Dump completed' | md5sum | cut -f1 -d' '
}

diff -q <(do_filter_sum one.gz) \
        <(do_filter_sum two.gz) \
        && echo same || echo not_same
0
27.01.2020, 19:58
  • 1
    md5sum является отходами, можно использовать cmp. zcat и grep может быть объединен в zgrep. –  Lekensteyn 14.03.2013, 18:22
  • 2
    , md5sum не необходим для сравнения (если Вам уже не генерировали их); я просто использовал его, так как derobert использовал его. zgrep является просто сценарием, который в основном делает gunzip и grep (или sed в зависимости от обстоятельств), таким образом, существует мало различия там. сценарий, столь же отправленный, намеренно показывается как цепочка каналов со сменными частями; какова забава в слиянии всего вниз в единственную команду? –  michael 14.03.2013, 22:19
  • 3
    И zcat справедливо gunzip -c. Используйте правильный инструмент для правильного задания, KISS лучше, чем чрезмерное увеличение размера. В этом случае я провел бы свое время при записи чего-то, что генерирует жесткие ссылки по мере необходимости, это представляет больший интерес. –  Lekensteyn 14.03.2013, 22:51

Теги

Похожие вопросы