mul*_*rse 11 python file extract overwrite ziparchive
有一些库用于通过Python提取存档文件,例如gzip,zipfile库,rarfile,tarfile,patool等.我发现其中一个库(patool)特别有用,因为它具有交叉格式功能它可以提取几乎任何类型的存档,包括最流行的存档,如ZIP,GZIP,TAR和RAR.
要使用patool提取存档文件,它就像这样简单:
patoolib.extract_archive( "Archive.zip",outdir="Folder1")
Run Code Online (Sandbox Code Playgroud)
其中"Archive.zip"
是存档文件"Folder1"
的路径,而是存储解压缩文件的目录的路径.
提取工作正常.问题是,如果我为完全相同的存档文件再次运行相同的代码,则相同的提取文件将存储在同一文件夹中,但名称略有不同(第一次运行时为文件名,第二次运行时为filename1,文件名为11)第三,等等.
如果目录中已经存在同名文件,我需要代码来覆盖提取的文件.
这个extract_archive
函数看起来很小 - 它只有这两个参数,一个verbosity
参数和一个program
参数,它指定了你想要提取档案的程序.
编辑:
Nizam Mohamed的回答记录了extract_archive
函数实际上覆盖了输出.我发现这部分是正确的 - 该函数会覆盖ZIP文件,但不会覆盖我所追求的GZ文件.对于GZ文件,该函数仍会生成新文件.
编辑 Padraic Cunningham的回答建议使用主源.因此,我下载了该代码,并用链接中的脚本替换了旧的patool库脚本.结果如下:
os.listdir()
Out[11]: ['a.gz']
patoolib.extract_archive("a.gz",verbosity=1,outdir=".")
patool: Extracting a.gz ...
patool: ... a.gz extracted to `.'.
Out[12]: '.'
patoolib.extract_archive("a.gz",verbosity=1,outdir=".")
patool: Extracting a.gz ...
patool: ... a.gz extracted to `.'.
Out[13]: '.'
patoolib.extract_archive("a.gz",verbosity=1,outdir=".")
patool: Extracting a.gz ...
patool: ... a.gz extracted to `.'.
Out[14]: '.'
os.listdir()
Out[15]: ['a', 'a.gz', 'a1', 'a2']
Run Code Online (Sandbox Code Playgroud)
因此,该extract_archive
功能再次在每次执行时创建新文件.存档的文件a.gz
具有与a
实际不同的名称.
正如您所说,patoolib 旨在成为一个通用的归档工具。
使用 patool 可以创建、提取、测试、列出、比较、搜索和重新打包各种存档类型。patool 的优点是处理存档文件的简单性,无需记住大量的程序和选项。
通用提取行为与特定提取行为
这里的问题是extract_archive
没有公开广泛修改存档工具的底层默认行为的能力。
对于 .zip 扩展名,patoolib 将使用 unzip。您可以通过将 -o 作为选项传递给命令行界面来获得提取存档的所需行为。ieunzip -o ...
但是,这是解压缩的特定命令行选项,并且每个存档实用程序都会发生变化。
例如,tar 提供了覆盖选项,但没有与 zip 等效的缩短命令行。即tar --overwrite
但tar -o
没有达到预期的效果。
要解决此问题,您可以向作者提出功能请求,或使用替代库。不幸的是,patoolib 的口头禅需要扩展所有提取实用程序函数,然后实现底层提取器自己的覆盖命令选项。
patoolib 的示例更改
在patoolib.programs.unzip
def extract_zip (archive, compression, cmd, verbosity, outdir, overwrite=False):
"""Extract a ZIP archive."""
cmdlist = [cmd]
if verbosity > 1:
cmdlist.append('-v')
if overwrite:
cmdlist.append('-o')
cmdlist.extend(['--', archive, '-d', outdir])
return cmdlist
Run Code Online (Sandbox Code Playgroud)
在patoolib.programs.tar
def extract_tar (archive, compression, cmd, verbosity, outdir, overwrite=False):
"""Extract a TAR archive."""
cmdlist = [cmd, '--extract']
if overwrite:
cmdlist.append('--overwrite')
add_tar_opts(cmdlist, compression, verbosity)
cmdlist.extend(["--file", archive, '--directory', outdir])
return cmdlist
Run Code Online (Sandbox Code Playgroud)
更新每个程序并不是一个简单的更改,每个程序都是不同的!
猴子修补覆盖行为
所以您决定不改进 patoolib 源代码...我们可以覆盖extract_archive
最初查找现有目录的行为,将其删除,然后调用原始extract_archive
.
您可以将此代码包含在您的模块中,如果许多模块需要它,也许坚持它__init__.py
import os
import patoolib
from shutil import rmtree
def overwrite_then_extract_archive(archive, verbosity=0, outdir=None, program=None):
if outdir:
if os.path.exists(outdir):
shutil.rmtree(outdir)
patoolib.extract_archive(archive, verbosity, outdir, program)
patoolib.extract_archive = overwrite_then_extract_archive
Run Code Online (Sandbox Code Playgroud)
现在,当我们调用时,extract_archive()
我们具有overwrite_then_extract_archive()
.
如果该功能不存在,您需要添加它。一个例子是用您自己的函数包装该函数:
import os
from shutil import rmtree
def overwriting_extract_archive(zippath, outpath, **kwargs):
if os.path.exists(outpath):
shutil.rmtree(outpath)
patoolib.extract_archive(zippath, outdir=outpath, **kwargs)
Run Code Online (Sandbox Code Playgroud)
如果您想逐个文件检查并将新输出与现有输出合并,这当然会成为一个更复杂的问题,但如果正如您所描述的那样(第二次运行它),这应该可行。