Python 文件权限中的 Zipfile
Posted
技术标签:
【中文标题】Python 文件权限中的 Zipfile【英文标题】:Zipfile in Python file permission 【发布时间】:2017-02-19 11:03:34 【问题描述】:我使用zipfile
lib从zip中提取文件,现在解压目录后发现我的文件权限已损坏,
import zipfile
fh = open('sample.zip', 'rb')
z = zipfile.ZipFile(fh)
print z.namelist()
for name in z.namelist():
z.extract(name, '/tmp/')
fh.close()
但是当我使用linux
解压缩工具时,这个问题不会发生
我尝试使用
os.system('unzip sample.zip')
但我仍然想用zipfile
来做这个
【问题讨论】:
这段代码适合我。我可以有源 zip 文件吗? 制作包含可执行文件的 zip 文件。由于某种原因,我无法上传源 zip 文件。 【参考方案1】:相关的 Python 问题提供了一些关于为什么首先存在问题的见解:https://bugs.python.org/issue18262 和 https://bugs.python.org/issue15795
此外,可以在此处找到原始 Zip 规范:https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
重要的部分是:
4.4.2版本(2字节) 4.4.2.1 高字节表示文件的兼容性 属性信息。如果外部文件属性 与 MS-DOS 兼容,可以通过 PKZIP 读取 DOS 版本 2.04g 那么这个值将为零。如果这些 属性不兼容,则此值将 识别属性所在的主机系统 兼容的。软件可以使用此信息来确定 文本文件等的行记录格式。 4.4.2.2 目前的映射是: 0 - MS-DOS 和 OS/2(FAT / VFAT / FAT32 文件系统) 1 - 阿米加 2 - OpenVMS 3 - UNIX 4 - 虚拟机/CMS 5 - 雅达利 ST 6 - OS/2 H.P.F.S. 7 - Macintosh 8 - Z 系统 9 - CP/M 10 - Windows NTFS 11 - MVS (OS/390 - Z/OS) 12 - VSE 13 - Acorn Risc 14 - VFAT 15 - 备用 MVS 16 - BeOS 17 - 串联 18 - OS/400 19 - OS X (Darwin) 20 到 255 - 未使用 ... 4.4.15 外部文件属性:(4字节) 外部属性的映射是 取决于主机系统(请参阅“制作的版本”)。为了 MS-DOS,低位字节是MS-DOS目录 属性字节。如果输入来自标准输入,则此 字段设置为零。这意味着外部文件属性是系统特定的。解释不同系统的外部文件属性可能会使情况变得更糟。如果我们只关心 UNIX,我们可以检查 ZipInfo.created_system
并将其与 3
(对于 UNIX)进行比较。不幸的是,规范并没有进一步帮助我们解释外部属性。
在这个 Wiki 中有一些东西http://forensicswiki.org/wiki/Zip#External_file_attributes
外部属性 UNIX (3) 大小为 4 个字节,包括: ╔═════════╦══════════╦════════╦═══════════════════ ════════════════════════════════════╗ ║ 偏移量 ║ 尺寸 ║ 值 ║ 描述 ║ ╠═════════╬══════════╬════════╬═══════════════════ ═════════════════════════════════════ ║ 0 ║ 1 ║ ║ FAT (MS-DOS) 文件属性。 ║ ║ 1 ║ 1 ║ ║ 未知 ║ ║ 2 ║ 16 位 ║ ║ UNIX 模式(或权限)。 ║ ║ ║ ║ ║ 该值似乎与 stat.st_mode 值相似。 ║ ╚═════════╩══════════╩════════╩═══════════════════ ════════════════════════════════════╝虽然这只是观察性的,但似乎是共识。
把这些放在一起:
from zipfile import ZipFile
ZIP_UNIX_SYSTEM = 3
def extract_all_with_permission(zf, target_dir):
for info in zf.infolist():
extracted_path = zf.extract(info, target_dir)
if info.create_system == ZIP_UNIX_SYSTEM:
unix_attributes = info.external_attr >> 16
if unix_attributes:
os.chmod(extracted_path, unix_attributes)
with ZipFile('sample.zip', 'r') as zf:
extract_all_with_permission(zf, '/tmp')
可能会出现一个问题,为什么我们首先要保留权限。有些人可能敢说我们只想保留可执行标志。在这种情况下,一个稍微安全一点的选择可能是只为文件恢复可执行标志。
from zipfile import ZipFile
from stat import S_IXUSR
ZIP_UNIX_SYSTEM = 3
def extract_all_with_executable_permission(zf, target_dir):
for info in zf.infolist():
extracted_path = zf.extract(info, target_dir)
if info.create_system == ZIP_UNIX_SYSTEM and os.path.isfile(extracted_path):
unix_attributes = info.external_attr >> 16
if unix_attributes & S_IXUSR:
os.chmod(extracted_path, os.stat(extracted_path).st_mode | S_IXUSR)
with ZipFile('sample.zip', 'r') as zf:
extract_all_with_executable_permission(zf, '/tmp')
【讨论】:
您已将同一问题 (bugs.python.org/issue18262) 关联了两次。除此之外,很好的答案! @FabioTurati 感谢您指出这一点。现在已经解决了。【参考方案2】:import zipfile
import os
unZipFile = zipfile.ZipFile("sample.zip", "r")
tmp_dir = "/tmp"
try:
for info in unZipFile.infolist():
real_path = unZipFile.extract(info, tmp_dir)
# permission
unix_attributes = info.external_attr >> 16
target = os.path.join(tmp_dir, info.filename)
if unix_attributes:
os.chmod(target, unix_attributes)
if not real_path:
print "Extract failed: " + info.filename
finally:
unZipFile.close()
【讨论】:
回答问题时,请提供与您的代码相关的解释。有些人可能不理解您的代码或看不到它如何回答问题。见how to write a good answer以上是关于Python 文件权限中的 Zipfile的主要内容,如果未能解决你的问题,请参考以下文章
云中的 Zipfile 文件(amazon s3),无需先将其写入本地文件(无写入权限)
Python 文件 IO 和 zipfile。尝试遍历文件夹中的所有文件,然后使用 Python 遍历相应文件中的文本