是否可以使用tarfile
从 TAR 存档中删除某些文件?
例如:
如果x.tar
文件包含文件a.txt
、b.txt
和c.txt
,是否可以删除a.txt
?
换句话说:是否存在任何 python 解决方案来实现这样的事情:
tar -vf x.tar --delete a.txt
?
不直接使用tarfile
,尽管可能还有其他一些库。您可以做的一个快速技巧是提取文件,然后重新创建tar
减去要删除的文件。
我遇到了类似的问题,最终使用了 7z 命令行 (7za.exe),因为它支持比 Python 的tarfile更多的功能,包括从存档中删除文件。
此解决方案的缺点是您需要随程序携带 7za.exe 文件。
在您的情况下,您可以使用类似的东西
os.system("7za d x.tar a.txt")
但请记住,os.system
已被弃用,您应该使用subprocess
.从来没有用过它,所以我真的帮不上更多忙。
事实上,有可能...但有巨大的限制。您只能删除存档的末尾/尾部,而不能删除存档开头或中间的文件.
我只是有类似的需求,即从巨大的 tar (450G) 中提取文件,没有足够的空间容纳 tar 和提取的文件。我必须一次提取一个文件,并在解压缩后立即将它们从.tar
中删除.
命令tar -vf x.tar --delete a.txt
不能解决这个问题,因为它不会从x.tar
中删除a.txt
(x.tar
保持相同的大小),它只是将其从包含的文件列表中删除(稍后解压缩x.tar
时不会提取a.txt
)。.tar
文件,您唯一能做的就是截断它们,因为它们是连续的。所以唯一的解决方案是从 end.
首先获取 tar 文件所有成员的列表:
with tarfile.open(name=tar_file_path, mode="r") as tar_file:
tar_members = tar_file.getmembers()
然后,您可以从末尾提取所需的文件:
with tarfile.open(name=tar_file_path, mode="r") as tar_file:
tar_file.extractall(path = extracting_dir, members = tar_members[first_of_files_to_extract:])
您可以计算截断文件的位置(以字节为单位):
truncate_size = tar_members[first_of_files_to_extract].offset
然后添加"文件结束"标记,即两个连续的 Null 块。每个块的长度为 512 字节.tar
,因此您需要在末尾有 1024 个空字节。在这里,仅作为记录,您可以添加 512 字节(一个块),因为前一个tar_member已经以 512 字节 Null 块(tar_member结尾的标记)完成。
new_file_size = truncate_size + 1024 # 2 blocs of 512 Null bytes
最后你做了截断,首先用于删除最后一个成员,其次用于添加空字节(这里我们不再打开带有tarfile.open()
的.tar
,截断只是常规的文件操作):
with open(tar_file_path) as tar_file:
tar_file.truncate(truncate_size)
tar_file.truncate(new_file_size)
在这里,您已经从.tar
末尾提取了文件,并且您有一个新的有效.tar
文件,通过提取文件的大小加上一些块字节,比前一个文件小,并且您已将额外的内存使用限制为提取文件的大小: 我个人逐个文件做了那个文件(提取最后一个文件, 截断,提取最后一个文件截断等)。