使用 Python 的 tarfile 时覆盖现有的只读文件
Posted
技术标签:
【中文标题】使用 Python 的 tarfile 时覆盖现有的只读文件【英文标题】:Overwrite existing read-only files when using Python's tarfile 【发布时间】:2011-11-06 10:32:10 【问题描述】:我正在尝试使用 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 中的只读文件、使用异常或类似的方法?
【问题讨论】:
【参考方案1】:您可以遍历 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
有一个覆盖选项会更好。
【讨论】:
太棒了 - 效果很好 =)。比盲目地吹走目录要干净得多。小澄清-您使用的是“with”,而我没有使用。我可能应该切换到那个 - 但是,我应该在哪里为整个 tarfile 插入“除了 ReadError”。据我了解,嵌套的 except 是不好的做法?with
语句将处理打开存档时引发的ReadError
异常。出错时它也会自动关闭文件。如果您想要更具体的错误处理,您可能希望在早期 try/except
中显式打开文件,或者您可能希望编写自己的上下文管理器以不同方式处理。
所以我在从 .tar.gz 中提取 .sh
文件时收到“拒绝访问”错误,这不是覆盖现有文件的问题 - dest 文件夹是空的。我认为这是由于“可执行”属性造成的?不知何故,用tarfile.open("1.tar.gz", "r:gz")
替换tarfile.open("1.tar.gz", "r")
解决了它。为什么?!根据文档,“r”与“r:*”相同,对于 .gz 存档为“r:gz”。
@stderr 为什么 os.chmod
在末尾的 finally
块中?解压出来的文件是不是不用重新设置就可以保留权限?
很好的答案——但你不是说“tar”而不是“tarball”(在没有“with”的例子中)。【参考方案2】:
我能够让 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)
【讨论】:
以上是关于使用 Python 的 tarfile 时覆盖现有的只读文件的主要内容,如果未能解决你的问题,请参考以下文章
python处理文件和文件的方法(shutil,filecmp ,MD5,tarfile,zip)
使用 Python 从仅具有基本名称的 tarfile 中提取文件
如何在不添加目录层次结构的情况下使用 Python 将文件添加到 tarfile?