我正在尝试使用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中的只读文件,使用异常或类似的东西?
答案 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)