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

发布于 2024-10-02 06:10:38 字数 604 浏览 7 评论 0原文

我想在将给定文件作为类文件对象获取之前,使用 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。

I would like to verify the existence of a given file in a tar archive with Python before I get it as a file-like object. I've tried it with isreg(), but probably I do something wrong.

How can I check if a file exists in a tar archive with Python?

I tried

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()

Probably tai is wrong. In fact tai.size() is always 0.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

Spring初心 2024-10-09 06:10:38

如果您确实需要检查,那么您可以使用 测试成员资格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
...

If you really need to check, then you can test for membership using the getnames method and the in operator:

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

However, I think that in Python (and dealing with file systems in general), catching exceptions are preferred. It's better to attempt to read and catch an exception because things can always happen between checking a file's existence and reading it later.

>>> try:
...     tar.getmember('contents.txt')
... except KeyError:
...     pass
...
涙—继续流 2024-10-09 06:10:38

也许使用 getnames() ?

tar = tarfile.open('sample.tar','r')
if 'test3.py' in tar.getnames():
    print 'test3.py is in sample.tar'

Maybe use getnames()?

tar = tarfile.open('sample.tar','r')
if 'test3.py' in tar.getnames():
    print 'test3.py is in sample.tar'
昔梦 2024-10-09 06:10:38

您可以使用 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

You can use tar.getnames() and the in operator to do it:

$ 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
云淡风轻 2024-10-09 06:10:38

即使 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())

This matches even if the tar file has the filename in a subdirectory, and uses normcase to mimic the filename case handling of the current OS (e.g. on Windows, searching for “readme.txt” should match “README.TXT” inside the tar file).

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())
幽梦紫曦~ 2024-10-09 06:10:38

要检索 tar 存档中的所有文件,您可以使用 getmembers()getnames()TarFile 对象的 a> 方法。然后,要提取它们,您可以使用 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 开始,添加了在 with 语句中使用 TarFile 对象作为上下文管理器的支持。

To retrieve all the files inside a tar archive you can use either the getmembers() or the getnames() methods of a TarFile object. Then, to extract them, you can use either the extract() or extractfile() methods.

For example:

# 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()

But take in mind that the names returned are actually relative file paths. Meaning that, if the "test1.txt" file you're looking for is stored in a "test" sub-directory inside the tar archive, than its TarInfo.name will actually be "test/test1.txt".

So, going back to the previous example, you should do something like:

# 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()

Finally, to test it, you can use @patch() to mock the tarfile.open().

For example:

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"
        ]

NOTE: As stated in the documentation, the support for using TarFile objects as context managers in with statements was added starting from version 3.2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文