代码之家  ›  专栏  ›  技术社区  ›  Tom Gruff

如何使用Python的zipfile模块对ZIP文件中的文件设置权限(属性)?

  •  38
  • Tom Gruff  · 技术社区  · 17 年前

    当我从用Python创建的ZIP文件中提取文件时 zipfile

    该文件是在Linux和Python 2.5.2下创建和提取的。

    据我所知,我需要设置 ZipInfo.external_attr

    7 回复  |  直到 12 年前
        1
  •  48
  •   Tom Gruff    13 年前

    这似乎是可行的(谢谢Evan,把它放在这里,让这句话符合上下文):

    buffer = "path/filename.zip"  # zip filename to write (or file-like object)
    name = "folder/data.txt"      # name of file inside zip 
    bytes = "blah blah blah"      # contents of file inside zip
    
    zip = zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED)
    info = zipfile.ZipInfo(name)
    info.external_attr = 0777 << 16L # give full access to included file
    zip.writestr(info, bytes)
    zip.close()
    

    我还是想看一些记录这件事的东西。。。我找到的另一个资源是关于Zip文件格式的说明: http://www.pkware.com/documents/casestudies/APPNOTE.TXT

        2
  •  26
  •   Community Mohan Dere    9 年前

    This link 比我在网上能找到的任何东西都要多。即使是zip源代码也没有任何内容。为后代复制相关章节。这个补丁实际上并不是关于记录这种格式,它只是用来显示当前文档是多么可怜(阅读不存在)。

    # external_attr is 4 bytes in size. The high order two
    # bytes represent UNIX permission and file type bits,
    # while the low order two contain MS-DOS FAT file
    # attributes, most notably bit 4 marking directories.
    if node.isfile:
        zipinfo.compress_type = ZIP_DEFLATED
        zipinfo.external_attr = 0644 << 16L # permissions -r-wr--r--
        data = node.get_content().read()
        properties = node.get_properties()
        if 'svn:special' in properties and \
               data.startswith('link '):
            data = data[5:]
            zipinfo.external_attr |= 0120000 << 16L # symlink file type
            zipinfo.compress_type = ZIP_STORED
        if 'svn:executable' in properties:
            zipinfo.external_attr |= 0755 << 16L # -rwxr-xr-x
        zipfile.writestr(zipinfo, data)
    elif node.isdir and path:
        if not zipinfo.filename.endswith('/'):
            zipinfo.filename += '/'
        zipinfo.compress_type = ZIP_STORED
        zipinfo.external_attr = 040755 << 16L # permissions drwxr-xr-x
        zipinfo.external_attr |= 0x10 # MS-DOS directory flag
        zipfile.writestr(zipinfo, '')
    

    而且 this link 在这里,低阶字节可能意味着四个字节中最右边(最低)的字节。所以这个是 对于MS-DOS,否则可以假定为零。

          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.
    

    另外,InfoZIP的zip程序源文件中的源文件unix/unix.c,从 Debian's archives 有以下评论。

      /* lower-middle external-attribute byte (unused until now):
       *   high bit        => (have GMT mod/acc times) >>> NO LONGER USED! <<<
       *   second-high bit => have Unix UID/GID info
       * NOTE: The high bit was NEVER used in any official Info-ZIP release,
       *       but its future use should be avoided (if possible), since it
       *       was used as "GMT mod/acc times local extra field" flags in Zip beta
       *       versions 2.0j up to 2.0v, for about 1.5 years.
       */
    

    综上所述,看起来实际上只使用了第二高的字节,至少在Unix中是这样。

    The zip format's external file attribute “。看起来我搞错了几件事。特别是前两个字节都用于Unix。

        3
  •  15
  •   Community Mohan Dere    9 年前

    看看这个: Set permissions on a compressed file in python

    我不完全确定这是否是你想要的,但似乎是。

    关键的一行似乎是:

    zi.external_attr = 0777 << 16L
    

    0777

        4
  •  9
  •   Alan Hazelden    8 年前

    先前的答案对我来说并不适用(在OSX10.12上)。我发现,除了可执行标志(octal 755),我还需要设置“常规文件”标志(octal 100000)。我发现这里提到了: https://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute

    一个完整的例子:

    zipname = "test.zip"
    filename = "test-executable"
    
    zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
    
    f = open(filename, 'r')
    bytes = f.read()
    f.close()
    
    info = zipfile.ZipInfo(filename)
    info.date_time = time.localtime()
    info.external_attr = 0100755 << 16L
    
    zip.writestr(info, bytes, zipfile.ZIP_DEFLATED)
    
    zip.close()
    

    这是我的一个特定用例的完整示例,创建一个.app的zip,以便文件夹中的所有内容 Contents/MacOS/ https://gist.github.com/Draknek/3ce889860cea4f59838386a79cc11a85

        5
  •  5
  •   Soroush mujjiga    5 年前

    您可以扩展 ZipFile 类更改默认文件权限:

    from zipfile import ZipFile, ZipInfo
    import time
    
    class PermissiveZipFile(ZipFile):
        def writestr(self, zinfo_or_arcname, data, compress_type=None):
            if not isinstance(zinfo_or_arcname, ZipInfo):
                zinfo = ZipInfo(filename=zinfo_or_arcname,
                                date_time=time.localtime(time.time())[:6])
    
                zinfo.compress_type = self.compression
                if zinfo.filename[-1] == '/':
                    zinfo.external_attr = 0o40775 << 16   # drwxrwxr-x
                    zinfo.external_attr |= 0x10           # MS-DOS directory flag
                else:
                    zinfo.external_attr = 0o664 << 16     # ?rw-rw-r--
            else:
                zinfo = zinfo_or_arcname
    
            super(PermissiveZipFile, self).writestr(zinfo, data, compress_type)
    

    此示例将默认文件权限更改为 664 775 目录。

        6
  •  1
  •   thakis    7 年前

    还要看什么 Python's zipfile module 做:

    def write(self, filename, arcname=None, compress_type=None):
        ...
        st = os.stat(filename)
        ...
        zinfo = ZipInfo(arcname, date_time)
        zinfo.external_attr = (st[0] & 0xFFFF) << 16L      # Unix attributes
        ...
    

    ```

        7
  •  1
  •   Maxim Masiutin    5 年前

    Python zipfile模块接受上述外部属性位中Unix ASi额外块的16位“Mode”字段(该字段存储struct stat中的st_Mode字段,包含用户/组/其他权限、setuid/setgid和符号链接信息等)。

    您还可以导入Python的“stat”模块以获得模式常量定义。

    您还可以在create_system中设置3,以指定创建ZIP存档的操作系统:3=Unix;0=Windows。

    以下是一个例子:

    #!/usr/bin/python
    
    import stat
    import zipfile
    
    def create_zip_with_symlink(output_zip_filename, link_source, link_target):
        zipInfo  = zipfile.ZipInfo(link_source)
        zipInfo.create_system = 3 
        unix_st_mode = stat.S_IFLNK | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH
        zipInfo.external_attr = unix_st_mode << 16 
        zipOut = zipfile.ZipFile(output_zip_filename, 'w', compression=zipfile.ZIP_DEFLATED)
        zipOut.writestr(zipInfo, link_target)
        zipOut.close()
    
    create_zip_with_symlink('cpuinfo.zip', 'cpuinfo.txt', '/proc/cpuinfo')
    
        8
  •  0
  •   Evan Fosmark    17 年前

    当你这样做的时候,它能正常工作吗?

    zf = zipfile.ZipFile("something.zip")
    for name in zf.namelist():
        f = open(name, 'wb')
        f.write(self.read(name))
        f.close()
    

    如果不是的话,我建议加入一个 os.chmod

    zf = zipfile.ZipFile("something.zip")
    for name in zf.namelist():
        f = open(name, 'wb')
        f.write(self.read(name))
        f.close()
        os.chmod(name, 0777)