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

19

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

Что вы хотите от различий? Список файлов (FileA существует в одном, но не в другом). Содержимое файлов (FileB в первом zip имеет эти модификации по сравнению с FileB во втором zip). Или все, что выше? Ответ eduffy может сработать (в Linux), если вас не волнует содержание. JMD
Это с юмором. Кто-то задает вопрос о программировании и получает много ответов, не связанных с программированием. :) EBGreen
Кроме того, какая платформа? Windows, Linux, другое? JMD
Если вам важно, совпадают ли заархивированные файлы, то почему бы не сравнить хэши? EBGreen
@Apple - вы, вероятно, должны опубликовать технологии, с которыми вы хотите сделать это. В частности, платформа и язык программирования, который вы планируете использовать. EBGreen

Ваш Ответ

12   ответов
5

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

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

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

2

но вы можете использовать приложение 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-архивах, но позволит вам быстро увидеть, какие файлы появляются в одном только архиве, а какие существуют в обоих, но имеют разное содержимое (то есть разный размер и / или контрольную сумму).

0

большой скрипт bash, который мне подходит:

#!/bin/bash
# Author: Onno Benschop, [email protected]
# 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

diffzips.pl

Он рекурсивно проверяет каждый zip-файл внутри исходного zip-файла, что особенно полезно для различных форматов пакетов Java: jar, war и ear.

zipcmp использует более простой подход, и он не превращается в заархивированные почтовые индексы.

7

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

@orangepips Это еще разархивирование, а затем диффузия, с дополнительным ограничением, характерным для gzip. Кроме того, ответ хаоса является лучшим решением для gzip-специфичных. Powerlord
@Powerlord: из любопытства ответ Эдуффи ненадежен? Или только позже, чем ваш комментарий? orangepips
К сожалению, это единственный надежный способ сделать это. Powerlord
Я стараюсь не открывать, не расширять и не рассеивать, это может быть дороже. ApplePieIsGood
0

WinMerge (только окна) имеет многофункции и один из них:

Поддержка архивных файлов с использованием 7-Zip
5

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

sudo apt-get установить zipcmp

«2380» = почтовый индекс въезда; «d0c49aea» - это md5 записи; Имя записи «c5-custom-product-5.2.0 / wso2 / runtime2 / bin / bootstrap / logging.properties». Посмотрите на md5, запись может быть одинакового размера, но разного содержания Wender
Не могли бы вы объяснить мне результат, полученный при запускеzipcmp Я получил строку ввода, как- 2380 d0c49aea c5-custom-product-5.2.0/wso2/runtime2/bin/bootstrap/logging.properties, я знаю- указывает на соответствующий почтовый файл, но то, что указано2380 а такжеd0c49aea, Спасибо Kasun Siyambalapitiya
34

# diff <(zcat file1.gz) <(zcat file2.gz)
Об этом приятно знать (я никогда не знал, что вы можете передавать два потока программы в другую программу, не создавая временных файлов.) Я был смущен и сталкивался с ошибками, пока не понял, что выне может быть пробела между <и paren. Joshua Goldberg
Ну, мне нужно сделать это программно, и я не работаю в среде Unix (к сожалению). ApplePieIsGood
Обратите внимание, что он также работает с заархивированными файлами:diff <(zcat file1.zip) <(zcat file2.zip) galath
как решение в этом ответе не "программно" решает вашу проблему? user3850
Также обратите внимание, что<(someCommand) синтаксис не вPOSIX, ВGNU Bash это наряду с>(someCommand) Синтаксис называетсяПроцесс замены и не доступен на всех платформах. jotik
1

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

С помощью gzip:

$ zdiff file1.gz file2.gz

С bzip2:

$ bzdiff file1.bz2 file2.bz2

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

1

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

@Richard: вы должны зарезервировать отрицательные ответы. Вопрос заключался в том, как различать два сжатых файла zip. Beyond Compare может быть не тем ответом, который вам нравится, но он не ошибается. Lieven Keersmaekers
BC работает с zip-файлом напрямую; ему не нужно извлекать все. Zips хранят CRC файлов как часть заголовка файла, поэтому для сравнений «CRC» или «на основе правил» мы можем сравнивать множество файлов, не распаковывая ничего. Для «двоичных» сравнений при проверке «похожих» файлов в сравнении на основе правил или при открытии в средстве просмотра файлов отдельные файлы будут распакованы. Небольшие файлы обрабатываются полностью в памяти, большие файлы могут храниться во временном каталоге. Zoë Peterson
Я уверен, что они расширяются за кулисами. Они должны иметь возможность показывать различия двух файлов из zip-архивов. Lieven Keersmaekers
Это собственность, так кто знает, что она делает? ctrl-alt-delor
Интересно, они расширяют это за кулисами и делают различия? Это то, что трудно сказать приложению, что оно делает. ApplePieIsGood
1

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)

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

0

s, но запускаю 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/
...
...

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