我正在使用 python 开发一个项目,其中我只需要提取 tar 存档的一个子文件夹,而不是所有文件。 我尝试使用
tar = tarfile.open(tarfile)
tar.extract("dirname", targetdir)
但这不起作用,它不会提取给定的子目录,也不会抛出异常。我是Python的初学者。 另外,如果上述函数不适用于目录,那么此命令和 tar.extractfile() 有什么区别?
基于 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 文件的根目录)。
另一个答案将保留子文件夹路径,这意味着
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))
所有其他解决方案的问题是它们需要在提取之前访问文件的末尾 - 这意味着它们不能应用于不支持查找的流。
使用 Python 3.12(我还没有找到早期版本的方法):
strip1 = lambda member, path: member.replace(name=pathlib.Path(*pathlib.Path(member.path).parts[1:]))
with tarfile.open('file.tar.gz', mode='r:gz') as input:
input.extractall(path=dest, filter=strip1)
extractall
接受一个过滤器,该过滤器会通过 TarInfo
为每个文件调用 - 您解压文件名,取出除第一个部分之外的所有部分,然后重新打包。