使用Python';时覆盖现有只读文件;焦油锉

使用Python';时覆盖现有只读文件;焦油锉,python,overwrite,tarfile,Python,Overwrite,Tarfile,我正试图使用Python的tarfile模块提取tar.gz归档文件 我希望提取覆盖任何已经存在的目标文件-这是tarfile的正常行为 但是,我遇到了一个小问题,因为有些文件上有写保护(例如chmod550) tarfile.extractall()操作实际上失败了: IOError: [Errno 13] Permission denied '/foo/bar/file' 如果我尝试从普通命令行删除文件,我可以做到,我只需要回答一个提示: $ rm <filename> rm:

我正试图使用Python的tarfile模块提取tar.gz归档文件

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

但是,我遇到了一个小问题,因为有些文件上有写保护(例如chmod550)

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

IOError: [Errno 13] Permission denied '/foo/bar/file'
如果我尝试从普通命令行删除文件,我可以做到,我只需要回答一个提示:

$ rm <filename>
rm: <filename>: override protection 550 (yes/no)? yes
$rm
rm::覆盖保护550(是/否)?对
普通的GNU tar实用程序也可以毫不费力地处理这些文件——它只是在提取时覆盖它们

我的用户是文件的所有者,因此在运行tarfile.extractall之前递归地对目标文件进行chmod并不困难。或者我可以使用shutil.rmtree预先吹走目标,这是我现在使用的解决方法。。然而,这让人觉得有点刻薄


是否有一种更类似python的方法来处理tarfile中的只读文件覆盖,使用异常或类似的方法?

您可以循环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)
如果不能将
一起使用,只需将
语句块替换为:

tarball = tarfile.open('myfile.tar', 'r', errorlevel=1)
for file_ in tar:
如果您的焦油球被压缩,有一个快速的快捷方式来处理它,只需:

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

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

我能够让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)

太棒了-效果很好=)。比盲目地吹走目录要干净得多。小澄清-你用的是“with”,我没有用。我可能应该切换到这一点——但是,我应该在哪里为整个tar文件插入“except ReadError”。据我所知,嵌套的except是一种不好的做法。
with
语句将处理打开归档文件时引发的
ReadError
异常。出现错误时,它还会自动关闭文件。如果您想要更具体的错误处理,您可能希望在早期的
try/except
中显式打开该文件,或者您可能希望编写自己的上下文管理器,以不同的方式处理问题。因此,从.tar.gz提取
.sh
文件时,我遇到了一个“拒绝访问”错误,这不是覆盖已有文件的问题——dest文件夹是空的。我想这是因为“可执行”属性?不知何故,用
tarfile.open(“1.tar.gz”,“r”)
替换
tarfile.open(“1.tar.gz”,“r:gz”)
解决了这个问题。为什么?根据文档,“r”与“r:*”相同,对于.gz归档文件来说,它是“r:gz”。@stderr为什么最后的
块中的
os.chmod
?提取的文件不需要再次设置权限就可以保留其权限吗?回答得好——但您的意思是“tar”而不是“tarball”(在don't have“with”示例中)。