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

时间:2011-08-30 00:18:39

标签: python overwrite tarfile

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

我希望提取覆盖它们已经存在的任何目标文件 - 这是tarfile的正常行为。

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

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

IOError: [Errno 13] Permission denied '/foo/bar/file'

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

$ rm <filename>
rm: <filename>: override protection 550 (yes/no)? yes

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

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

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

2 个答案:

答案 0 :(得分:8)

你可以遍历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)

如果您无法使用with,只需将with语句块替换为:

tarball = tarfile.open('myfile.tar', 'r', errorlevel=1)
for file_ in tar:

如果您的tar球被gzip压缩,那么只需使用快捷方式处理它:

tarfile.open('myfile.tar.gz', 'r:gz')

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

答案 1 :(得分:1)

我能够让Mike的Steder代码像这样工作:

tarball = tarfile.open(filename, 'r:gz')
for f in tarball:
    try: 
        tarball.extract(f)
    except IOError as e:
        os.remove(f.name)
        tarball.extract(f)
    finally:
        os.chmod(f.name, f.mode)