Вопрос

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

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

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

Спасибо,

Это было полезно?

Решение

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

Другие советы

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


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


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

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

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

Пример 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/

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

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

pkgdiff PKG-0.tgz PKG-1.tgz

enter image description here

enter image description here

Вот мой вариант, он тоже проверяет разрешение 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)

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

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

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

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

Если архивы не извлекаются и различия не нужны, попробуйте разница's -q вариант:

diff -q 1.tar 2.tar

Это тихий результатом будет "1.деготь 2.деготь отличается" или ничего, если нет различий.

Существует инструмент под названием архидифф.По сути, это perl-скрипт, который может просматривать архивы.

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

У меня есть похожий вопрос, и я решаю его с помощью 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")

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

pip install diffoscope

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

#!/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]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top