如何使用Python检查tar归档文件中是否存在一个文件?

3
我希望在获取文件对象之前,能够用Python验证tar归档文件中给定文件的存在性。我已经尝试使用isreg(),但可能我做错了什么。
如何使用Python检查文件是否存在于tar归档文件中?
我已经尝试过:
import tarfile


tar = tarfile.open("sample.tar", "w")
tar.add("test1.txt")
tar.add("test2.txt")
tar.add("test3.py")
tar.close()

tar = tarfile.open("sample.tar", "r")
tai = tar.tarinfo(name="test3.py")
print(tai.isreg())
print(tai.size())
tar.close()

可能 tai 是错误的。事实上,tai.size() 总是为0。

5个回答

6

如果你真的需要检查,那么你可以使用getnames方法和in操作符来测试成员资格:

>>> import tarfile
>>> tar = tarfile.open("sample.tar", "w")
>>> "sample.tar" in tar.getnames()
True

然而,在Python中(以及处理文件系统的一般情况下),捕获异常是更好的选择。最好尝试读取并捕获异常,因为在检查文件存在性和稍后读取之间总是会发生意外情况。

>>> try:
...     tar.getmember('contents.txt')
... except KeyError:
...     pass
...

0

要检索tar归档文件中的所有文件,您可以使用TarFile对象的getmembers()getnames()方法。然后,要提取它们,您可以使用extract()extractfile()方法。

例如:

# Archive: "sample.tar" >> Content: "test1.txt", ...
filename = "test1.txt"
with tarfile.open("sample.tar", "r") as tar:
    if filename in tar.getnames():
        file = tar.extractfile(filename).read()

但请记住,返回的名称实际上是相对文件路径。这意味着,如果您要查找的"test1.txt"文件存储在tar归档文件内的"test"子目录中,则其TarInfo.name实际上将是"test/test1.txt"

因此,回到之前的例子,您应该执行类似以下操作:

# Archive: "sample.tar" >> Content: "test", "test/test1.txt", ...
filename = "test1.txt"
with tarfile.open("sample.tar", "r") as tar:
    for name in tar.getnames():
        if name.endswith(filename):
            file = tar.extractfile(name).read()

最后,为了测试它,您可以使用@patch()来模拟tarfile.open()

例如:

import unittest
from unittest.mock import patch

class TestTarfile(unittest.TestCase):
    @patch('myfile.tarfile.open')
    def test_tarfile_open(self, mock_open):
        mock_open.return_value.__enter__.return_value.getnames.return_value = [
            "test",
            "test/test1.txt"
        ]

注意:根据文档,从3.2版本开始,支持将TarFile对象作为上下文管理器在with语句中使用。


0
也许可以使用getnames()函数吗?
tar = tarfile.open('sample.tar','r')
if 'test3.py' in tar.getnames():
    print 'test3.py is in sample.tar'

0

即使tar文件中的文件名位于子目录中,并使用normcase来模拟当前操作系统的文件名大小写处理(例如,在Windows上,搜索“readme.txt”应该匹配tar文件中的“README.TXT”)。

def filename_in_tar(filename, atarfile):
    filename= os.path.normcase(filename)
    return any(
        filename == os.path.normcase(os.path.basename(tfn))
        for tfn in atarfile.getnames())

0
你可以使用tar.getnames()in运算符来实现这个功能:
$ touch a.txt
$ tar cvf a.tar a.txt
$ python
>>> names = tarfile.open('a.tar').getnames()
>>> 'a.txt' in names
True
>>> 'b.txt' in names
False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接