Есть ли безопасный способ запустить diff на двух сжатых файлах zip? - PullRequest
19 голосов
/ 25 февраля 2009

Кажется, это не будет детерминированной вещью, или есть способ сделать это надежно?

Ответы [ 12 ]

35 голосов
/ 25 февраля 2009

Если вы используете gzip, вы можете сделать что-то вроде этого:

# diff <(zcat file1.gz) <(zcat file2.gz)
7 голосов
/ 25 февраля 2009

Надежно: разархивировать оба, разн.

Понятия не имею, достаточно ли этого ответа для вашего использования, но он работает.

5 голосов
/ 18 января 2017

zipcmp сравнивает zip-архивы zip1 и zip2 и проверяет, содержат ли они одинаковые файлы, сравнивая их имена, несжатые размеры и CRC. Порядок файлов и сжатые размеры игнорируются.

sudo apt-get install zipcmp

5 голосов
/ 26 февраля 2009

В общем, вы не можете избежать распаковки и последующего сравнения. Разные компрессоры приводят к разным потокам байтов DEFLATEd, которые при INFLATEd приводят к одному и тому же исходному тексту. Вы не можете просто сравнить данные DEFLATEd друг с другом. Это не удастся в некоторых случаях.

Но в сценарии ZIP для каждой записи вычисляется и сохраняется CRC32. Поэтому, если вы хотите проверить файлы, вы можете просто сравнить сохраненный CRC32, связанный с каждым потоком DEFLATEd, с предостережениями относительно свойств уникальности хэша CRC32. Это может соответствовать вашим потребностям для сравнения FileName и CRC.

Вам понадобится библиотека ZIP, которая читает файлы ZIP и предоставляет эти вещи в качестве свойств объекта "ZipEntry". DotNetZip сделает это для приложений .NET.

2 голосов
/ 13 декабря 2010

Это не особенно элегантно, но вы можете использовать приложение FileMerge, которое поставляется с инструментами разработчика Mac OS X, для сравнения содержимого zip-файлов с помощью пользовательского фильтра.

Создать скрипт ~/bin/zip_filemerge_filter.bash с содержанием:

#!/bin/bash
##
#  List the size, CR-32 checksum, and file path of each file in a zip archive,
#  sorted in order by file path.
##
unzip -v -l "${1}" | cut -c 1-9,59-,49-57 | sort -k3
exit $?

Сделать скрипт исполняемым (chmod +x ~/bin/zip_filemerge_filter.bash).

Откройте FileMerge, откройте «Настройки» и перейдите на вкладку «Фильтры». Добавьте элемент в список с помощью: Расширение: "zip", Фильтр: "~ / bin / zip_filemerge_filter.bash $ (FILE)", Отображение: Отфильтровано, Применить *: Нет (я также добавил файлер для файлов .jar и .war.)

Затем используйте FileMerge (или оболочку командной строки «opendiff»), чтобы сравнить два файла .zip.

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

1 голос
/ 12 сентября 2017

Python-решение для zip-файлов:

import difflib
import zipfile

def diff(filename1, filename2):
    differs = False

    z1 = zipfile.ZipFile(open(filename1))
    z2 = zipfile.ZipFile(open(filename2))
    if len(z1.infolist()) != len(z2.infolist()):
        print "number of archive elements differ: {} in {} vs {} in {}".format(
            len(z1.infolist()), z1.filename, len(z2.infolist()), z2.filename)
        return 1
    for zipentry in z1.infolist():
        if zipentry.filename not in z2.namelist():
            print "no file named {} found in {}".format(zipentry.filename,
                                                        z2.filename)
            differs = True
        else:
            diff = difflib.ndiff(z1.open(zipentry.filename),
                                 z2.open(zipentry.filename))
            delta = ''.join(x[2:] for x in diff
                            if x.startswith('- ') or x.startswith('+ '))
            if delta:
                differs = True
                print "content for {} differs:\n{}".format(
                    zipentry.filename, delta)
    if not differs:
        print "all files are the same"
        return 0
    return 1

Использовать как

diff(filename1, filename2)

Он сравнивает файлы построчно в памяти и показывает изменения.

1 голос
/ 19 декабря 2013

На самом деле gzip и bzip2 поставляются с выделенными инструментами для этого.

С помощью gzip:

$ zdiff file1.gz file2.gz

С bzip2:

$ bzdiff file1.bz2 file2.bz2

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

1 голос
/ 25 февраля 2009

Вне сравнения не имеет проблем с этим.

0 голосов
/ 04 июня 2018

Я отказался от попыток использовать существующие инструменты и написал небольшой скрипт bash, который работает для меня:

#!/bin/bash
# Author: Onno Benschop, onno@itmaze.com.au
# Note: This requires enough space for both archives to be extracted in the tempdir

if [ $# -ne 2 ] ; then
  echo Usage: $(basename "$0") zip1 zip2
  exit
fi

# Make temporary directories
archive_1=$(mktemp -d)
archive_2=$(mktemp -d)

# Unzip the archives
unzip -qqd"${archive_1}" "$1"
unzip -qqd"${archive_2}" "$2"

# Compare them
diff -r "${archive_1}" "${archive_2}"

# Remove the temporary directories
rm -rf "${archive_1}" "${archive_2}"
0 голосов
/ 12 июля 2017

Обычно я использую такой подход, как @ mrabbit, но запускаю 2 команды распаковки и выводим данные по мере необходимости. Например, мне нужно сравнить 2 файла Java WAR.

$ sdiff --width 160 \
   <(unzip -l -v my_num1.war | cut -c 1-9,59-,49-57 | sort -k3) \
   <(unzip -l -v my_num2.war | cut -c 1-9,59-,49-57 | sort -k3)

В результате получается вывод:

--------          -------                                                       --------          -------
Archive:                                                                        Archive:
-------- -------- ----                                                          -------- -------- ----
48619281          130 files                                                   | 51043693          130 files
    1116 060ccc56 index.jsp                                                         1116 060ccc56 index.jsp
       0 00000000 META-INF/                                                            0 00000000 META-INF/
     155 b50f41aa META-INF/MANIFEST.MF                                        |      155 701f1623 META-INF/MANIFEST.MF
 Length   CRC-32  Name                                                           Length   CRC-32  Name
    1179 b42096f1 version.jsp                                                       1179 b42096f1 version.jsp
       0 00000000 WEB-INF/                                                             0 00000000 WEB-INF/
       0 00000000 WEB-INF/classes/                                                     0 00000000 WEB-INF/classes/
       0 00000000 WEB-INF/classes/com/                                                 0 00000000 WEB-INF/classes/com/
...
...
...