您好,我目前正在使用一种必须提取一些.tar文件的工具。
在大多数情况下效果很好,但我有一个问题:
某些.tar和.zip文件的名称包含“非法”字符(例如“ .ex”:“)。 该程序必须在Windows机器上运行,所以我必须对此进行处理。
如果其中包含“:”或另一个非法的Windows字符,是否可以更改提取的输出中某些文件的名称。
我当前的实现方式:
conflicts.Abort
所以目前我只是忽略了这些输出,这并不理想。
为了更好地描述我的要求,我可以举一个小例子:
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
唯一的解决方案是遍历压缩文件中的每个文件对象并一步一步提取,还是有一个更优雅的解决方案?
答案 0 :(得分:1)
根据[Python 3]: ZipFile.extract(member, path=None, pwd=None):
在Windows上,非法字符(
:
,<
,>
,|
,"
,?
和*
)替换为下划线(_
)。
所以,事情已经解决了:
>>> 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 (源文件和文档)并没有发现类似的内容(如果没有的话, .tar 格式主要用于 Nix ),因此您必须手动进行操作。事情并没有我预想的那么简单,因为 tarfile 不能像 zipfile 那样提供使用不同名称提取成员的可能性。
无论如何,这是一段代码(我有 zipfile 和 tarfile 作为灵感或灵感来源):
def read_tar(filepath, extractpath="."):
win_illegal = ':<>|"?*'
table = str.maketrans(win_illegal, '_' * len(win_illegal))
with tarfile.open(filepath, "r:gz") as tar:
for member in tar.getmembers():
if member.isdir():
os.makedirs(member.path.translate(table))
else:
with open(os.path.join(extractpath, member.path.translate(table)), "wb") as fout:
fout.write(tarfile.ExFileObject(tar, member).read())
请注意,上面的代码适用于简单的 .tar 文件(具有简单的成员,包括目录),但我没有对其健壮性进行测试。
@ EDIT0 :
添加了目录处理。
@ EDIT1 :
已提交[Python.Bugs]: tarfile: handling Windows (path) illegal characters in archive member names。
我不知道它的结果如何,因为我提交了一些更严重的问题(并针对它们进行了修复)(在我的 PoV 上),但是对于出于各种原因,他们被拒绝了。