40

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

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

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

ありがとう、

4

12 に答える 12

20

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

pkgdiff PKG-0.tgz PKG-1.tgz

ここに画像の説明を入力してください

ここに画像の説明を入力してください

于 2016-03-01T21:58:24.530 に答える
11

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


tarファイルを1つだけ抽出する余裕がある場合は、オプションを使用して--difftar、他のtarファイルの内容との違いを探すことができます。


ファイル名とそのサイズを比較するだけで問題がない場合は、もう1つの大雑把なトリックが必要です。
これは、他のファイルが同じであることを保証するものではないことを忘れないでください。

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

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

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/

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

于 2009-06-23T04:50:31.277 に答える
7

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

于 2009-06-23T05:18:22.130 に答える
7

編集:@StéphaneGourichonによるコメントを参照してください

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

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

引数の順序が重要であることに注意してください。特にO、どの信号がstdoutを使用するか。

于 2015-03-30T22:45:28.463 に答える
6

これが私の変種です。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)
于 2013-05-14T09:43:08.050 に答える
2

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

于 2009-06-23T03:54:36.527 に答える
2

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

pip install diffoscope
于 2019-02-28T12:45:41.267 に答える
1

Goで書いたgtarsumを提案します。これは、自律実行可能ファイルになることを意味します(Pythonやその他の実行環境は必要ありません)。

go get github.com/VonC/gtarsum

tarファイルを読み取ります。

  • ファイルのリストをアルファベット順に並べ替えます。
  • ファイルの内容ごとにSHA256を計算します。
  • それらのハッシュを1つの巨大な文字列に連結します
  • その文字列のSHA256を計算します

結果は、ファイルとそのコンテンツのリストに基づいたtarファイルの「グローバルハッシュ」です。

複数のtarファイルを比較し、同一の場合は0を返し、同一でない場合は1を返します。

于 2020-09-08T07:55:58.957 に答える
1

上記の解決策はどれも私が必要としていたものには機能しなかったので、これを捨てるだけです。

この関数は、指定されたパスに一致するすべてのファイルパスのmd5ハッシュのmd5ハッシュを取得します。ハッシュが同じである場合、ファイル階層とファイルリストは同じです。

他の人ほどパフォーマンスが良くないことは知っていますが、必要な確実性を提供します。

PATH_TO_CHECK="some/path"
for template in $(find build/ -name '*.tar'); do
    tar -xvf $template --to-command=md5sum | 
        grep $PATH_TO_CHECK -A 1 | 
        grep -v $PATH_TO_CHECK | 
        awk '{print $1}' | 
        md5sum | 
        awk "{print \"$template\",\$1}"
done

*注:無効なパスは単に何も返しません。

于 2021-07-26T06:12:32.340 に答える
0

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

diff -q 1.tar 2.tar

この静かな結果は、「1.tar 2.tarが異なる」か、違いがない場合は何もありません。

于 2013-05-09T14:38:29.083 に答える
0

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

Takes two archives, or an archive and a directory and shows a summary of the
differences between them.
于 2014-04-18T07:50:24.337 に答える
0

同様の質問があり、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")
于 2016-12-10T13:08:14.660 に答える