2つのtarballのコンテンツを比較する方法
-
06-07-2019 - |
質問
2つのtarballファイルに、日付、ユーザー、グループなどのメタデータを含まず、ファイル名とファイルの内容に関して同一のファイルが含まれているかどうかを確認したい。
ただし、いくつかの制限があります。 まず、tarファイルを作成するときにメタデータを含めるかどうかを制御できません。実際には、tarファイルには常にメタデータが含まれているため、2つのtarファイルを直接比較しても機能しません。 第二に、一部のtarファイルは非常に大きいため、一時ディレクトリにtarを展開して、含まれているファイルを1つずつ比較することはできません。 (file1.tarをfile1 /にuntarできるかどうかはわかっていますが、file /で 'tar -dvf file2.tar'を呼び出すことでそれらを比較できます。しかし、通常、そのうちの1つでもuntarする余裕はありません)
2つのtarファイルを比較する方法はありますか? SHELLスクリプト内で実現できればより良いでしょう。あるいは、実際にtarballを展開せずに各サブファイルのチェックサムを取得する方法はありますか?
ありがとう、
解決
tarsum はほとんど必要なものです。その出力を取得し、ソートを実行してそれぞれで同じ順序を取得し、2つをdiffと比較します。これで基本的な実装が行われるはずです。Pythonコードを変更してジョブ全体を実行することで、これらの手順をメインプログラムに簡単に組み込むことができます。
他のヒント
これらのtarファイルの作成を制御していますか?
もしそうなら、 MD5チェックサムを作成し、アーカイブ自体内のファイルに保存することが最善の策です。次に、2つのファイルを比較する場合、このチェックサムファイルを抽出して比較します。
1つのtarファイルのみを抽出する余裕がある場合、 tar
の-diff
オプションを使用できます他の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つ取得して、それらを比較できます。
日付と時刻の列を使用することもできます。
また、 pkgdiff を試して、パッケージの違いを視覚化します(追加/削除/名前変更されたファイルと変更されたコンテンツを検出し、変更されていない場合はゼロコードで存在します):
pkgdiff PKG-0.tgz PKG-1.tgz
これは私の亜種で、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を使用するようにシグナルを送ります。
探しているのは tardiff ですか? 「シンプルなperlスクリプト」です。 &quot; 2つのtarballの内容を比較し、それらの間に見つかった相違点について報告します。&quot;
アーカイブを抽出せず、差分を必要としない場合は、 diff を試してください。の -q オプション:
diff -q 1.tar 2.tar
この quiet の結果は、&quot; 1.tar 2.tar different&quot; か、違いがない場合は何もありません。
archdiff というツールがあります。基本的に、アーカイブを調べることができるperlスクリプトです。
Takes two archives, or an archive and a directory and shows a summary of the
differences between them.
同様の質問がありますが、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")
diffoscope もあります。これはより一般的で、さまざまな形式を含む再帰的な比較を可能にします。
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 "簡単なスクリプトを使用できます:
diff-tars.sh TAR1 TAR2 [DIFF_OPTS]
使用法:
<*>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"
使用法:
<*>