[英]Zipfile in Python file permission
i used zipfile
lib to extract file from zip and now after unzip the directory i found the permission of my file has been corrupted , 我使用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()
but when i use linux
unzip tools this issue don't happen i try to use 但是当我使用linux
解压缩工具时,不会发生此问题,我尝试使用
os.system('unzip sample.zip')
but i still want to do this with zipfile
但是我仍然想用zipfile
做到这一点
The related Python issues provide some insight as to why the issue existed in the first place: https://bugs.python.org/issue18262 and https://bugs.python.org/issue15795 相关的Python问题提供了关于为什么首先存在该问题的一些见解: https : //bugs.python.org/issue18262和https://bugs.python.org/issue15795
Additionally the original Zip spec can be found here: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT 此外,原始的Zip规范可以在以下位置找到: https : //pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
The important sections are: 重要的部分是:
4.4.2 version made by (2 bytes) 4.4.2.1 The upper byte indicates the compatibility of the file attribute information. If the external file attributes are compatible with MS-DOS and can be read by PKZIP for DOS version 2.04g then this value will be zero. If these attributes are not compatible, then this value will identify the host system on which the attributes are compatible. Software can use this information to determine the line record format for text files etc. 4.4.2.2 The current mappings are: 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) 1 - Amiga 2 - OpenVMS 3 - UNIX 4 - VM/CMS 5 - Atari ST 6 - OS/2 H.P.F.S. 7 - Macintosh 8 - Z-System 9 - CP/M 10 - Windows NTFS 11 - MVS (OS/390 - Z/OS) 12 - VSE 13 - Acorn Risc 14 - VFAT 15 - alternate MVS 16 - BeOS 17 - Tandem 18 - OS/400 19 - OS X (Darwin) 20 thru 255 - unused ... 4.4.15 external file attributes: (4 bytes) The mapping of the external attributes is host-system dependent (see 'version made by'). For MS-DOS, the low order byte is the MS-DOS directory attribute byte. If input came from standard input, this field is set to zero.
That means that the external file attributes are system specific. 这意味着外部文件属性是系统特定的。 Interpreting the external file attributes for a different system could potentially make it worse. 解释其他系统的外部文件属性可能会使情况更糟。 If we only care about UNIX, we could check the ZipInfo.created_system
and compare it with 3
(for UNIX). 如果仅关心UNIX,则可以检查ZipInfo.created_system
并将其与3
(对于UNIX)进行比较。 Unfortunately the spec doesn't help us much further in how to interpret the external attributes. 不幸的是,该规范在解释外部属性方面并没有进一步帮助我们。
There is something in this Wiki http://forensicswiki.org/wiki/Zip#External_file_attributes 该Wiki中有一些内容http://forensicswiki.org/wiki/Zip#External_file_attributes
The external attributes UNIX (3) is 4 bytes of size and consists of: ╔═════════╦══════════╦════════╦═══════════════════════════════════════════════════════╗ ║ Offset ║ Size ║ Value ║ Description ║ ╠═════════╬══════════╬════════╬═══════════════════════════════════════════════════════╣ ║ 0 ║ 1 ║ ║ FAT (MS-DOS) file attributes. ║ ║ 1 ║ 1 ║ ║ Unknown ║ ║ 2 ║ 16 bits ║ ║ The UNIX mode (or permission). ║ ║ ║ ║ ║ The value seems to be similar to stat.st_mode value. ║ ╚═════════╩══════════╩════════╩═══════════════════════════════════════════════════════╝
While that is rather observational, it seems to be the consensus. 虽然这是观察性的,但似乎是共识。
Putting this together: 放在一起:
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')
There may be a question coming up why we want to preserve the permissions in the first place. 可能会有一个问题,为什么我们要首先保留权限。 Some may dare to say that we only want to keep the executable flag. 有人可能敢说我们只想保留可执行标志。 A slightly safer option in that case could be to only restore the executable flag, for files only. 在这种情况下,较为安全的选择是仅针对文件还原可执行标志。
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')
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()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.