Как сравнить два тарболла - PullRequest
28 голосов
/ 23 июня 2009

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

Однако существуют некоторые ограничения: Во-первых, у меня нет контроля над тем, включены ли метаданные при создании файла tar. Фактически, файл tar всегда содержит метаданные, поэтому прямая разность двух файлов tar не работает. Во-вторых, так как некоторые tar-файлы настолько велики, что я не могу позволить себе распаковать их во временный каталог и разослать содержащиеся в них файлы один за другим. (Я знаю, могу ли я распаковать файл file1.tar в файл file1 /, я могу сравнить их, вызвав tar -dvf file2.tar в файле /. Но обычно я не могу позволить себе распаковать даже один из них)

Есть идеи, как я могу сравнить два файла tar? Было бы лучше, если бы это можно было выполнить в сценариях SHELL. В качестве альтернативы, есть ли способ получить контрольную сумму каждого подфайла, не распаковывая архив?

Спасибо

Ответы [ 11 ]

11 голосов
/ 23 июня 2009

Контролируете ли вы создание этих tar-файлов?
Если это так, то лучший способ - создать контрольную сумму MD5 и сохранить ее в файле в самом архиве. Затем, когда вы хотите сравнить два файла, вы просто извлекаете эти файлы контрольной суммы и сравниваете их.


Если вы можете позволить извлечь только один файл tar , , вы можете использовать опцию --diff tar, чтобы искать различия с содержимым другого файла tar.


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

выполнить tar tvf, чтобы составить список содержимого каждого файла и сохранить результаты в двух разных файлах. затем нарежьте все, кроме имени файла и столбцов размера. Желательно сортировать два файла тоже. Затем просто выполните файл diff между двумя списками.

Просто помните, что эта последняя схема на самом деле не выполняет контрольную сумму.

Пример tar и вывода (в этом примере все файлы имеют нулевой размер).

$ tar tvfj pack1.tar.bz2
drwxr-xr-x user/group 0 2009-06-23 10:29:51 dir1/
-rw-r--r-- user/group 0 2009-06-23 10:29:50 dir1/file1
-rw-r--r-- user/group 0 2009-06-23 10:29:51 dir1/file2
drwxr-xr-x user/group 0 2009-06-23 10:29:59 dir2/
-rw-r--r-- user/group 0 2009-06-23 10:29:57 dir2/file1
-rw-r--r-- user/group 0 2009-06-23 10:29:59 dir2/file3
drwxr-xr-x user/group 0 2009-06-23 10:29:45 dir3/

Команда для создания отсортированного списка имен / размеров

$ tar tvfj pack1.tar.bz2 | awk '{printf "%10s %s\n",$3,$6}' | sort -k 2
0 dir1/
0 dir1/file1
0 dir1/file2
0 dir2/
0 dir2/file1
0 dir2/file3
0 dir3/

Вы можете взять два таких отсортированных списка и сравнить их.
Вы также можете использовать столбцы даты и времени, если это работает для вас.

11 голосов
/ 02 марта 2016

Попробуйте также pkgdiff для визуализации различий между пакетами (обнаруживает добавленные / удаленные / переименованные файлы и измененный контент, существует с нулевым кодом, если он не изменился):

pkgdiff PKG-0.tgz PKG-1.tgz

enter image description here

enter image description here

5 голосов
/ 31 марта 2015

Я понимаю, что это поздний ответ, но я натолкнулся на нить, пытаясь добиться того же самого.Реализованное мной решение выводит tar в stdout и направляет его в любой хэш, который вы выберете:

tar -xOzf archive.tar.gz | sort | sha1sum

Обратите внимание, что порядок аргументов важен;особенно O, который сигнализирует использовать стандартный вывод.

4 голосов
/ 14 мая 2013

Вот мой вариант, он также проверяет разрешение unix:

Работает только в том случае, если имена файлов короче 200 символов.

diff <(tar -tvf 1.tar | awk '{printf "%10s %200s %10s\n",$3,$6,$1}'|sort -k2) <(tar -tvf 2.tar|awk '{printf "%10s %200s %10s\n",$3,$6,$1}'|sort -k2)
3 голосов
/ 23 июня 2009

лапка - это почти то, что вам нужно. Возьмите выходные данные, выполните сортировку, чтобы получить одинаковый порядок сортировки для каждого, а затем сравните их с разницей. Это должно дать вам базовую реализацию, и было бы достаточно легко внедрить эти шаги в основную программу, изменив код Python для выполнения всей работы.

2 голосов
/ 23 июня 2009

Является ли tardiff тем, что вы ищете? Это «простой скрипт на Perl», который «сравнивает содержимое двух тарболов и сообщает о любых найденных различиях».

0 голосов
/ 28 февраля 2019

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

pip install diffoscope
0 голосов
/ 10 декабря 2016

У меня есть похожий вопрос, и я решаю его с помощью Python, вот код. PS: хотя этот код используется для сравнения содержимого двух zipball, но он похож на tarball, надеюсь, я могу помочь вам

import zipfile
import os,md5
import hashlib
import shutil

def decompressZip(zipName, dirName):
    try:
        zipFile = zipfile.ZipFile(zipName, "r")
        fileNames = zipFile.namelist()
        for file in fileNames:
            zipFile.extract(file, dirName)
        zipFile.close()
        return fileNames
    except Exception,e:
        raise Exception,e

def md5sum(filename):
    f = open(filename,"rb")
    md5obj = hashlib.md5()
    md5obj.update(f.read())
    hash = md5obj.hexdigest()
    f.close()
    return str(hash).upper()

if __name__ == "__main__":
    oldFileList = decompressZip("./old.zip", "./oldDir")
    newFileList = decompressZip("./new.zip", "./newDir")

    oldDict = dict()
    newDict = dict()

    for oldFile in oldFileList:
        tmpOldFile = "./oldDir/" + oldFile
        if not os.path.isdir(tmpOldFile):
            oldFileMD5 = md5sum(tmpOldFile)
            oldDict[oldFile] = oldFileMD5

    for newFile in newFileList:
        tmpNewFile = "./newDir/" + newFile
        if not os.path.isdir(tmpNewFile):
            newFileMD5 = md5sum(tmpNewFile)
            newDict[newFile] = newFileMD5

    additionList = list()
    modifyList = list()

    for key in newDict:
        if not oldDict.has_key(key):
            additionList.append(key)
        else:
            newMD5 = newDict[key]
            oldMD5 = oldDict[key]
            if not newMD5 == oldMD5:
            modifyList.append(key)

    print "new file lis:%s" % additionList
    print "modified file list:%s" % modifyList

    shutil.rmtree("./oldDir")
    shutil.rmtree("./newDir")
0 голосов
/ 10 июня 2015

Можно использовать простой скрипт:

#!/usr/bin/env bash
set -eu

tar1=$1
tar2=$2
shift 2
tar_opts=("$@")

tmp1=`mktemp -d`
_trap="rm -r "$tmp1"; ${_trap:-}" && trap "$_trap" EXIT
tar xf "$tar1" -C "$tmp1"

tmp2=`mktemp -d`
_trap="rm -r "$tmp2"; ${_trap:-}" && trap "$_trap" EXIT
tar xf "$tar2" -C "$tmp2"

diff -ur "${tar_opts[@]:+${tar_opts[@]}}" "$tmp1" "$tmp2"

Использование:

diff-tars.sh TAR1 TAR2 [DIFF_OPTS]
0 голосов
/ 18 апреля 2014

Существует инструмент под названием archdiff . Это в основном Perl-скрипт, который может просматривать архивы.

Takes two archives, or an archive and a directory and shows a summary of the
differences between them.
...