似乎这不是一个确定性的事情,或者有没有办法可靠地做到这一点?
答案 0 :(得分:35)
如果你正在使用gzip,你可以这样做:
# diff <(zcat file1.gz) <(zcat file2.gz)
答案 1 :(得分:7)
可靠:解压缩,差异。
我不知道这个答案是否适合您的使用,但它确实有用。
答案 2 :(得分:5)
一般来说,你无法避免解压缩然后比较。不同的压缩器将导致不同的DEFLATEd字节流,当INFLATEd导致相同的原始文本时。您不能简单地将DEFLATEd数据相互比较。在某些情况下,这将失败。
但在ZIP方案中,为每个条目计算并存储了CRC32。因此,如果要检查文件,可以简单地比较与每个DEFLATEd流关联的存储CRC32,以及CRC32哈希的唯一性属性的警告。它可能符合您比较FileName和CRC的需要。
您需要一个ZIP库来读取zip文件并将这些内容公开为“ZipEntry”对象上的属性。 DotNetZip将为.NET应用程序做到这一点。
答案 3 :(得分:5)
zipcmp 比较zip存档zip1和zip2,并检查它们是否包含相同的文件,比较它们的名称,未压缩的大小和CRC。文件顺序和压缩的大小差异将被忽略。
sudo apt-get install zipcmp
答案 4 :(得分:2)
这不是特别优雅,但您可以使用Mac OS X开发人员工具附带的FileMerge应用程序来使用自定义过滤器比较zip文件的内容。
创建包含内容的脚本~/bin/zip_filemerge_filter.bash
:
#!/bin/bash
##
# List the size, CR-32 checksum, and file path of each file in a zip archive,
# sorted in order by file path.
##
unzip -v -l "${1}" | cut -c 1-9,59-,49-57 | sort -k3
exit $?
使脚本可执行(chmod +x ~/bin/zip_filemerge_filter.bash
)。
打开FileMerge,打开“首选项”,然后转到“过滤器”选项卡。使用以下内容将项添加到列表: 扩展名:“zip”,过滤器:“〜/ bin / zip_filemerge_filter.bash $(FILE)”,显示:过滤,应用*:否。(我还为.jar和.war文件添加了文件管理器。)
然后使用FileMerge(或命令行“opendiff”包装器)来比较两个.zip文件。
这不会让您在zip存档中区分文件的内容,但是可以让您快速查看哪些文件只显示在一个存档中,哪些文件存在于两个存档中但具有不同的内容(即不同的大小和/或校验和) )。
答案 5 :(得分:1)
Beyond compare对此没有任何问题。
答案 6 :(得分:1)
实际上gzip和bzip2都带有专用工具。
使用gzip:
$ zdiff file1.gz file2.gz
使用bzip2:
$ bzdiff file1.bz2 file2.bz2
但请记住,对于非常大的文件,您可能会遇到内存问题(我最初是为了了解如何解决它们,所以我还没有答案)。
答案 7 :(得分:1)
用于zip文件的python解决方案:
import difflib
import zipfile
def diff(filename1, filename2):
differs = False
z1 = zipfile.ZipFile(open(filename1))
z2 = zipfile.ZipFile(open(filename2))
if len(z1.infolist()) != len(z2.infolist()):
print "number of archive elements differ: {} in {} vs {} in {}".format(
len(z1.infolist()), z1.filename, len(z2.infolist()), z2.filename)
return 1
for zipentry in z1.infolist():
if zipentry.filename not in z2.namelist():
print "no file named {} found in {}".format(zipentry.filename,
z2.filename)
differs = True
else:
diff = difflib.ndiff(z1.open(zipentry.filename),
z2.open(zipentry.filename))
delta = ''.join(x[2:] for x in diff
if x.startswith('- ') or x.startswith('+ '))
if delta:
differs = True
print "content for {} differs:\n{}".format(
zipentry.filename, delta)
if not differs:
print "all files are the same"
return 0
return 1
用作
diff(filename1, filename2)
它在内存中逐行比较文件并显示更改。
答案 8 :(得分:0)
答案 9 :(得分:0)
我对这个简单的Perl脚本感到宽慰:diffzips.pl
它递归地区分原始zip中的每个zip文件,这对于不同的Java包格式特别有用:jar,war和ear。
zipcmp使用更简单的方法,并且不会递归到存档的拉链。
答案 10 :(得分:0)
我通常使用像@ mrabbit这样的方法,但运行2个解压缩命令并根据需要对输出进行区分。例如,我需要比较2个Java WAR文件。
$ sdiff --width 160 \
<(unzip -l -v my_num1.war | cut -c 1-9,59-,49-57 | sort -k3) \
<(unzip -l -v my_num2.war | cut -c 1-9,59-,49-57 | sort -k3)
导致输出如此:
-------- ------- -------- -------
Archive: Archive:
-------- -------- ---- -------- -------- ----
48619281 130 files | 51043693 130 files
1116 060ccc56 index.jsp 1116 060ccc56 index.jsp
0 00000000 META-INF/ 0 00000000 META-INF/
155 b50f41aa META-INF/MANIFEST.MF | 155 701f1623 META-INF/MANIFEST.MF
Length CRC-32 Name Length CRC-32 Name
1179 b42096f1 version.jsp 1179 b42096f1 version.jsp
0 00000000 WEB-INF/ 0 00000000 WEB-INF/
0 00000000 WEB-INF/classes/ 0 00000000 WEB-INF/classes/
0 00000000 WEB-INF/classes/com/ 0 00000000 WEB-INF/classes/com/
...
...
答案 11 :(得分:0)
我放弃了尝试使用现有工具并编写了一个适合我的小bash脚本:
#!/bin/bash
# Author: Onno Benschop, onno@itmaze.com.au
# Note: This requires enough space for both archives to be extracted in the tempdir
if [ $# -ne 2 ] ; then
echo Usage: $(basename "$0") zip1 zip2
exit
fi
# Make temporary directories
archive_1=$(mktemp -d)
archive_2=$(mktemp -d)
# Unzip the archives
unzip -qqd"${archive_1}" "$1"
unzip -qqd"${archive_2}" "$2"
# Compare them
diff -r "${archive_1}" "${archive_2}"
# Remove the temporary directories
rm -rf "${archive_1}" "${archive_2}"
答案 12 :(得分:0)
这里的许多解决方案要么只是检查CRC,以查看是否存在差异 ,它们是复杂的脚本,需要解压缩到磁盘,使用外部程序,还是需要除一种以外的特定压缩格式您在问(zcat does NOT work with zip)。
这是一种简单,易于阅读的方法,并且可以在显示bash显示文件内容之间差异的任何地方工作。
diff \
<(zipinfo -1 "$zip1" '*' \
| grep '[^/]$' \
| sort \
| while IFS= read -r file; do unzip -c "$zip1" "$file"; done \
) \
<(zipinfo -1 "$zip2" '*' \
| grep '[^/]$' \
| sort \
| while IFS= read -r file; do unzip -c "$zip2" "$file"; done \
)
这会在内存中进行解压缩,而不是对磁盘进行解压缩,从而在差异化时从管道中释放数据(它不会解压缩,然后然后进行比较,因此不应使用太多内存)。
是否要更改差异选项以忽略空白或并排使用?将diff
更改为diff -w
或gvimdiff
(此文件会将所有文件保留在内存中)等。
假设您只想比较.js
文件?将*
更改为*.js
。
只想查看一个或另一个缺少的文件名?删除while
行,它就不会再解压缩了。
容易
它甚至可以安全地处理(跳过并记录到stderr
)文件名中,并使用“非法”字符(例如换行符和反斜杠)。
不会比这更“安全”。
slm的答案非常适合返回不同的文件(不显示差异),甚至根本不解压缩,这很好。如果出于某种原因,您希望在CRC之上,而在CRC之上,则可以在| sha512sum
之前添加; done
,得到“两全其美”:P
类似地,比较存档和真实目录相对容易:
diff \
<(zipinfo -1 "$zip" '*' \
| grep '[^/]$' \
| sort \
| while IFS= read -r file; do unzip -c "$zip" "$file"; done \
) \
<(find "$directory" -type f -name '*' \
| sort \
| while IFS= read -r file
do
printf 'Archive: %s\n inflating: %s\n' "$directory" `echo $file | sed "s|$directory/||"`
cat "$file"
echo
done \
)
或者,仅忽略目录中的文件,基本上是unzip -o -d "$directory"
的便捷试运行:
diff \
<(zipinfo -1 "$zip" '*' \
| grep '[^/]$' \
| sort \
| while IFS= read -r file; do unzip -c "$zip" "$file"; done \
) \
<(zipinfo -1 "$zip" '*' \
| grep '[^/]$' \
| sort \
| while IFS= read -r file
do
printf 'Archive: %s\n inflating: %s\n' "$directory" "$file"
cat "$directory/$file"
echo
done \
)
Windows?抱歉。尽管脚本很简单,并且可以轻松移植到[语法上]出色的Powershell,但它无法正常工作。本地cmdlet only extracts to disk和MS still 尚未修复broken binary data piping in PS,因此您也不能以这种方式“安全”使用外部zip.exe
。
其他人也使用.NET API directly做过类似的事情,但是它变得不再是优雅的移植,而更多地是在.NET中的重新实现:|
关于前面提到的“非法文件名”的说明:
如果您希望它与这些协同工作,实际上并不是很困难;您只需要将$file
与$(echo "$file" | sed 's/\\/\\\\/g;s/\^J/\n/g;s/\^M/\r/g')
交换即可。
添加其他ctrl chars时会遇到它们。
原因是由于某种原因,即使zipinfo
在其中以\n
显示带有^J
的文件名时,它也不会接受{{1 }},只有原始的!即使它可以使用unzip -^
提取到那些非法文件名,也根本无法通过unzip
获得这些原始文件名。因此,您需要从安全的,无法使用的文件中构建原始的非法文件名,以为diff引用它们:(
如果执行此操作,请注意,无法从字面上区分zipinfo
和显示为^J
的{{1}},并且该zip不支持\n
或{{1 }}中的所有文件名。
作为奖励;您可以将所有这些差异直接写入归档文件,并将其全部保存在与原始文件匹配的文件夹层次结构中,而不必试图一次读取所有差异。
^J
虽然不是一个漂亮的脚本,但是现在您可以在您选择的gui存档器中将其打开,或者执行/
来查看与该文件的区别,或者如果找不到该文件,则被“找不到”问候差异,这在实践中更漂亮。