正确区分压缩的 .gz 文件和归档的 tar.gz 文件?

Posted

技术标签:

【中文标题】正确区分压缩的 .gz 文件和归档的 tar.gz 文件?【英文标题】:Differentiating between compressed .gz files and archived tar.gz files properly? 【发布时间】:2016-08-23 23:03:19 【问题描述】:

区分 gzip 或 bzip2 格式的普通压缩文件(例如 .gz)和使用 gzip 或 bzip2 压缩的 tarball(例如 .tar.gz)的正确方法是什么一个可靠的选择,因为文件可能最终会被重命名。

现在在命令行上我可以做这样的事情:

bzip2 -dc test.tar.bz2 |head|file -

所以我尝试在 python 中使用以下函数进行类似的操作:

def get_magic(self, store_file, buffer=False, look_deeper=False):
    # see what we're indexing
    if look_deeper == True:
        m = magic.Magic(mime=True, uncompress=True)
    else:
        m = magic.Magic(mime=True) 

    if buffer == False:
        try:
            file_type = m.from_file(store_file)

        except Exception, e:
            raise e

    else:
        try:
            file_type = m.from_buffer(store_file)

        except Exception, e:
            raise e

    return file_type 

然后,当尝试读取压缩的 tarball 时,我将从其他地方通过以下方式传入缓冲区:

    file_buffer = open(file_name).read(8096) 
    archive_check = self.get_magic(file_buffer, True, True)

不幸的是,使用 python-magic 中的 uncompress 标志会出现问题,因为 python-magic 似乎希望我传递整个文件,即使我只希望它读取缓冲区。我最终得到了例外:

bzip2 ERROR: Compressed file ends unexpectedly

看到我正在查看的文件最终可能是 2M 到 20GB 的大小,这变得相当有问题。我不想阅读整个文件

它可以被破解并切断压缩文件的末尾并将其附加到缓冲区吗?是否最好忽略使用 python-magic 解压缩文件的想法,而是在我传入缓冲区以通过以下方式识别之前执行它:

    file_buffer = open(file_name, "r:bz2").read(8096) 

有没有更好的办法?

【问题讨论】:

【参考方案1】:

如果偏移量 257 处的未压缩数据为“ustar”,则很可能是 tar 文件,如果未压缩数据整体为 1024 个零字节(一个空的 tar 文件)。 p>

您可以使用z = zlib.decompressobj()z = bz2.BZ2Decompressor()z.decompress() 仅读取未压缩数据的前1024 个字节。

【讨论】:

【参考方案2】:

实际上,我会将马克的答案标记为正确的答案,因为它给了我提示。

我最终放弃了这个项目来做其他事情长达六个月,并且因为 bz2.BZ2Decompressor 似乎没有按照它应该做的那样做而被难住了。事实证明,这个问题在 1024 字节内是无法解决的。

#!/usr/bin/env python

import os
import bz2
import magic

store_file = "10mb_test_file.tar.bz2"
m = magic.Magic(mime=True)

file_buffer = open(store_file, "rb").read(1000000)
buffer_chunk = ""

decompressor = bz2.BZ2Decompressor()
print ( "encapsulating bz2" )
print ( type(file_buffer) )
print ( len(file_buffer) )
file_type = m.from_buffer(file_buffer)
print ( "file type: %s :" % file_type)

buffer_chunk += decompressor.decompress( file_buffer )
print ( "compressed file contents" )
print ( type(buffer_chunk) )
print ( len(buffer_chunk) )

file_type = m.from_buffer(buffer_chunk)
print ( "file type: %s :" % file_type)

奇怪的是,对于 20MB 的 tar.bz2 文件,我可以使用 200,000 字节而不是 1,000,000 字节的值,但该值不适用于 10MB 的测试文件。我不知道它是否特定于所涉及的 tar.bz2 存档,并且我没有研究所涉及的算法以查看它们是否处于特定点,但到目前为止读取大约 10MB 的数据似乎对每个存档文件都有效到 5GB。 open().read(buffer) 将读取到缓冲区或 EOF 的大小,所以这没关系。

【讨论】:

以上是关于正确区分压缩的 .gz 文件和归档的 tar.gz 文件?的主要内容,如果未能解决你的问题,请参考以下文章

Linux中文档的压缩和打包

tar gz bz2 xz zip z归档压缩解压缩

压缩与归档

RHCSA-A13. 创建归档打包压缩文件夹

linux 下 压缩命令都有哪些?那个压缩比最高?

Linux 命令详解-存档压缩