gpt4 book ai didi

python - Tarfile/Zipfile extractall() 更改某些文件的文件名

转载 作者:行者123 更新时间:2023-12-01 08:09:37 25 4
gpt4 key购买 nike

您好,我目前正在开发一个必须提取一些 .tar 文件的工具。

它在大多数情况下都工作得很好,但我有一个问题:

某些 .tar 和 .zip 文件的名称包含“非法”字符(f.ex“:”)。这个程序必须在 Windows 机器上运行,所以我必须处理这个问题。

如果提取的输出中包含“:”或其他非法 Windows 字符,我是否可以更改某些文件的名称。

我当前的实现:

def read_zip(filepath, extractpath):
with zipfile.ZipFile(filepath, 'r') as zfile:
contains_bad_char = False
for finfo in zfile.infolist():
if ":" in finfo.filename:
contains_bad_char = True
if not contains_bad_char:
zfile.extractall(path=extractpath)


def read_tar(filepath, extractpath):
with tarfile.open(filepath, "r:gz") as tar:
contains_bad_char = False
for member in tar.getmembers():
if ":" in member.name:
contains_bad_char = True
if not contains_bad_char:
tar.extractall(path=extractpath)

所以目前我只是忽略这些输出,这并不理想。

为了更好地描述我的要求,我可以提供一个小例子:

file_with_files.tar -> small_file_1.txt
-> small_file_2.txt
-> annoying:file_1.txt
-> annoying:file_1.txt

应该提取到

file_with_files -> small_file_1.txt
-> small_file_2.txt
-> annoying_file_1.txt
-> annoying_file_1.txt

迭代压缩文件中的每个文件对象并一一提取是唯一的解决方案还是有更优雅的解决方案?

最佳答案

根据[Python.Docs]: ZipFile.extract(member, path=None, pwd=None) :

On Windows illegal characters (:, <, >, |, ", ?, and *) replaced by underscore (_).

所以,事情已经解决了:

>>> import os
>>> import zipfile
>>>
>>> os.getcwd()
'e:\\Work\\Dev\\StackOverflow\\q055340013'
>>> os.listdir()
['arch.zip']
>>>
>>> zf = zipfile.ZipFile("arch.zip")
>>> zf.namelist()
['file0.txt', 'file:1.txt']
>>> zf.extractall()
>>> zf.close()
>>>
>>> os.listdir()
['arch.zip', 'file0.txt', 'file_1.txt']

快速浏览TarFile(源代码和doc)并没有发现任何类似的东西(如果没有的话我也不会感到非常惊讶,因为< em>.tar 格式主要用于 Nix),因此您必须手动执行此操作。事情并不像我想象的那么简单,因为 TarFile 不提供以不同名称提取成员的可能性,就像 ZipFile 那样。
无论如何,这是一段代码(我有ZipFileTarFile作为缪斯或灵感来源):

code00.py:

#!/usr/bin/env python

import sys
import os
import tarfile


def unpack_tar(filepath, extractpath=".", compression_flag="*"):
win_illegal = ':<>|"?*'
table = str.maketrans(win_illegal, '_' * len(win_illegal))
with tarfile.open(filepath, "r:" + compression_flag) as tar:
for member in tar.getmembers():
#print(member, member.isdir(), member.name, member.path)
#print(type(member))
if member.isdir():
os.makedirs(member.path.translate(table), exist_ok=True)
else:
with open(os.path.join(extractpath, member.path.translate(table)), "wb") as fout:
fout.write(tarfile.ExFileObject(tar, member).read())


def main(*argv):
unpack_tar("arch00.tar")


if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)

请注意,上述代码适用于简单的 .tar 文件(具有简单的成员,包括目录)。

已提交[Python.Bugs]: tarfile: handling Windows (path) illegal characters in archive member names
我不知道它的结果会是什么,因为我提交了几个更严重的问题(以及对它们的修复)(根据我的PoV),但是对于种种原因,都被拒绝了。

关于python - Tarfile/Zipfile extractall() 更改某些文件的文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55340013/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com