使用Python的tarfile时覆盖现有的只读文件

vic*_*ooi 10 python overwrite tarfile

我正在尝试使用Python的tarfile模块来提取tar.gz存档.

我想要提取来覆盖它们已经存在的任何目标文件 - 这是tarfile的正常行为.

但是,我发现有些文件具有写保护功能(例如chmod 550).

tarfile.extractall()操作实际上失败:

IOError: [Errno 13] Permission denied '/foo/bar/file'
Run Code Online (Sandbox Code Playgroud)

如果我尝试从正常的命令行删除文件,我可以这样做,我只需要回答提示:

$ rm <filename>
rm: <filename>: override protection 550 (yes/no)? yes
Run Code Online (Sandbox Code Playgroud)

普通的GNU tar实用程序也可以毫不费力地处理这些文件 - 它只是在提取时覆盖它们.

我的用户是文件的所有者,因此在运行tarfile.extractall之前递归chmod目标文件并不困难.或者我可以使用shutil.rmtree预先吹走目标,这是我现在正在使用的解决方法..但是,这感觉有点hackish.

是否有更多的Pythonic方法来处理tarfile中的只读文件,使用异常或类似的东西?

std*_*err 9

您可以遍历tarball的成员并提取/处理每个文件的错误:

在现代版本的Python中我会使用以下with语句:

import os, tarfile

with tarfile.TarFile('myfile.tar', 'r', errorlevel=1) as tar:
    for file_ in tar:
        try:
            tar.extract(file_)
        except IOError as e:
            os.remove(file_.name)
            tar.extract(file_)
        finally:
            os.chmod(file_.name, file_.mode)
Run Code Online (Sandbox Code Playgroud)

如果你不能使用with只需将with语句块替换为:

tarball = tarfile.open('myfile.tar', 'r', errorlevel=1)
for file_ in tar:
Run Code Online (Sandbox Code Playgroud)

如果你的tar球被gzip压缩,那么就可以通过以下方式快速处理它:

tarfile.open('myfile.tar.gz', 'r:gz')
Run Code Online (Sandbox Code Playgroud)

如果tarfile.extractall有覆盖选项会更好.