2017-02-19 135 views
1

我用zipfile LIB来提取zip文件,现在解压我发现我的文件的权限已损坏的目录后,zip文件Python中的文件权限

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

+0

此代码适合我。我可以有源zip文件吗? –

+0

在里面制作带有可执行文件的zip文件。由于某些原因,我无法上传源zip文件。 – Rome

回答

4

相关Python的问题提供一些见解,为什么摆在首位存在的问题:https://bugs.python.org/issue18262https://bugs.python.org/issue15795

另外原来邮编规范可以在这里找到:https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT

最重要的部分是:

 
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. 

这意味着外部文件属性是系统特定的。解释不同系统的外部文件属性可能会使情况变得更糟。如果我们只关心UNIX,我们可以检查ZipInfo.created_system并与3(用于UNIX)进行比较。不幸的是,这个规范并没有帮助我们进一步解释外部属性。

也有一些是在这个维基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. ║ 
╚═════════╩══════════╩════════╩═══════════════════════════════════════════════════════╝ 

虽然这是相当的观察,它似乎是共识。

把这个在一起:

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') 
+0

您已经将相同的问题(https://bugs.python.org/issue18262)链接了两次。除此之外,很好的答案! –

+0

@FabioTurati谢谢你指出。现在已经解决了。 – de1

0
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() 
+0

回答问题时,请提供与您的代码相关的解释。有些人可能不了解你的代码,或者没有看到它如何回答这个问题。请参阅[如何写出一个好的答案](https://stackoverflow.com/help/how-to-answer) – Nuageux