web-dev-qa-db-ja.com

2つのtarballのコンテンツを比較する方法

2つのtarballファイルに、日付、ユーザー、グループなどのメタデータを含まない、ファイル名とファイルの内容に関して同一のファイルが含まれているかどうかを確認したいと思います。

ただし、いくつかの制限があります。まず、tarファイルを作成するときにメタデータを含めるかどうかを制御できません。実際、tarファイルには常にメタデータが含まれているため、2つのtarファイルを直接比較することはできません。次に、一部のtarファイルは非常に大きいため、一時ディレクトリに解凍して、含まれているファイルを1つずつ比較する余裕がありません。 (file1.tarをfile1 /にuntarできるかどうかはわかっていますが、file /で 'tar -dvf file2.tar'を呼び出すことで比較できます。ただし、通常は、そのうちの1つでもuntarを使用する余裕はありません)

2つのtarファイルを比較する方法はありますか?シェルスクリプト内で実行できるとよいでしょう。または、実際にtarballを解凍せずに各サブファイルのチェックサムを取得する方法はありますか?

ありがとう、

28
myjpa

tarsum はほとんどあなたが必要とするものです。その出力を取得し、並べ替えを実行してそれぞれの順序が同じになるようにしてから、2つをdiffと比較します。これで基本的な実装が可能になります。Pythonコードを変更してジョブ全体を実行することで、これらのステップをメインプログラムに簡単に取り込むことができます。

3
Greg Smith

これらのtarファイルの作成を制御していますか?
もしそうなら、 最善の策は、MD5チェックサムを作成してファイルに保存することです。 アーカイブ自体の中で。次に、2つのファイルを比較する場合は、このチェックサムファイルを抽出して比較するだけです。


余裕があれば tarファイルを1つだけ抽出します、 tar--diffオプションを使用できます 他のtarファイルの内容との違いを探すため。


もう1つの大雑把なトリック あなたがただで大丈夫なら ファイル名とそのサイズの比較
これは他のファイルが同じであることを保証するものではないことを忘れないでください!

tar tvfを実行して各ファイルの内容を一覧表示し、出力を2つの異なるファイルに保存します。次に、ファイル名とサイズの列以外のすべてを切り取ります。できれば2つのファイルもソートしてください。次に、2つのリスト間でファイル差分を実行します。

この最後のスキームは実際にはチェックサムを実行しないことを覚えておいてください。

サンプルのタールと出力(この例では、すべてのファイルのサイズはゼロです)。

$ 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/

あなたは2つのそのようなソートされたリストを取り、それらを比較することができます。
それがうまくいく場合は、日付と時刻の列を使用することもできます。

11
nik

また、 pkgdiff を試して、パッケージ間の違いを視覚化します(追加/削除/名前変更されたファイルと変更されたコンテンツを検出し、変更されていない場合はコードなしで存在します):

pkgdiff PKG-0.tgz PKG-1.tgz

enter image description here

enter image description here

11
linuxbuild

これは返信が遅いことに気づきましたが、同じことを達成しようとしているときにスレッドに出くわしました。私が実装したソリューションは、tarをstdoutに出力し、選択したハッシュにパイプします。

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

引数の順序が重要であることに注意してください。特にOは、stdoutを使用するように通知します。

5

これが私の変種です。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)
5
user1126070

tardiff あなたが探しているものですか?これは、「2つのtarballの内容を比較し、それらの間に見つかった違いを報告する」「単純なPerlスクリプト」です。

2
Evan

archdiff というツールがあります。これは基本的に、アーカイブを調べることができるPerlスクリプトです。

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

diffoscope もあります。これはより一般的で、再帰的に比較できます(さまざまな形式を含む)。

pip install diffoscope
0
Kuchara

アーカイブを抽出せず、違いが必要ない場合は、 diff 's-qオプションを試してください。

diff -q 1.tar 2.tar

このquietの結果は、 "1.tar 2.tar different"になるか、違いがない場合は何もありません。

0
Alastair

私は同様の質問があり、Pythonで解決します。ここにコードがあります。 ps:このコードは2つの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
Jason Swift