从tar文件中仅提取单个目录(使用Python)

12
我正在用Python开发一个项目,需要从tar归档文件中提取一个子文件夹而不是所有文件。我尝试使用

tar = tarfile.open(tarfile)
tar.extract("dirname", targetdir)

但是它不起作用,它没有提取给定的子目录,也没有抛出异常。我是Python的初学者。 另外,如果上述函数不适用于目录,那么这个命令和tar.extractfile()之间有什么区别?


extractfile() 不会将文件写入磁盘,它只会返回一个 Python 对象。而 extract() 则会将文件写入磁盘。 - ed.
2个回答

22

tarfile 模块文档 的第二个示例基础上,您可以使用以下代码提取包含的子文件夹及其所有内容:

with tarfile.open("sample.tar") as tar:
    subdir_and_files = [
        tarinfo for tarinfo in tar.getmembers()
        if tarinfo.name.startswith("subfolder/")
    ]
    tar.extractall(members=subdir_and_files)

这将创建一个子文件夹及其内容的列表,然后使用推荐的extractall()方法仅提取它们。当然,将"subfolder/"替换为您想要提取的子文件夹的实际路径(相对于tar文件的根目录)。


16

另一个答案将保留子文件夹路径,这意味着subfolder/a/b将被提取到./subfolder/a/b。要将子文件夹提取到根目录中,使subfolder/a/b提取到./a/b,您可以使用类似于以下内容的代码重写路径:

def members(tf):
    l = len("subfolder/")
    for member in tf.getmembers():
        if member.path.startswith("subfolder/"):
            member.path = member.path[l:]
            yield member

with tarfile.open("sample.tar") as tar:
    tar.extractall(members=members(tar))

2
非常好用。您还可以通过执行 member.path = os.path.join('new_dirname', member.path[l:]) 来使用此样式重命名顶级文件夹。 - Blake
很好的提示。每次都有许多无用的子目录被提取出来真的很烦人。 - user8491363
这个很好用。不幸的是,我之前只看了最佳答案,所以跳过了这个答案。 - Ramesh
抱歉,我会删除它。不好意思,我希望得到一个非常相似问题的答案。顺便说一句,这个解决方案对我不起作用。我收到了一个错误:[Pyright reportGeneralTypeIssues] [E]类型为“Generator[TarInfo, None, None]”的参数无法分配给函数“extractall”中类型为“List[TarInfo] | None”的参数“members” 类型“Generator[TarInfo, None, None]”无法分配给类型“List[TarInfo] | None” “Generator[TarInfo, None, None]”与“List[TarInfo]”不兼容 无法分配给“None” - Folaht
1
更容易打开一个新问题,而不是留下没有足够信息的评论。如果在Python中运行代码,则代码可以正常工作。您显示的错误是静态类型错误,不会阻止代码正常运行。该错误的修复方法:https://github.com/python/typeshed/pull/5273 - Sam Bull

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