Come posso impostare le autorizzazioni (attributi) su un file in un file ZIP usando il modulo zipfile Python?

StackOverflow https://stackoverflow.com/questions/434641

Domanda

Quando estraggo file da un file ZIP creato con Python zipfile , tutti i file non sono scrivibili, di sola lettura ecc.

Il file viene creato ed estratto in Linux e Python 2.5.2.

Come meglio posso dire, ho bisogno di impostare la proprietà ZipInfo.external_attr per ogni file, ma questo non sembra essere documentato ovunque io possa trovare, qualcuno può illuminarmi?

È stato utile?

Soluzione

Questo sembra funzionare (grazie Evan, mettendolo qui in modo che la linea sia nel contesto):

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

Mi piacerebbe ancora vedere qualcosa che documentasse questo ... Un'ulteriore risorsa che ho trovato era una nota sul formato del file Zip: http://www.pkware.com/documents/casestudies/APPNOTE.TXT

Altri suggerimenti

Questo link contiene più informazioni di qualunque altra cosa in grado di trovare in rete. Anche la fonte zip non ha nulla. Copia della sezione pertinente per i posteri. Questa patch non riguarda davvero la documentazione di questo formato, il che dimostra semplicemente quanto sia patetica (leggi inesistente) la documentazione attuale.

# 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, '')

Inoltre, questo link ha il seguente. Qui il byte di ordine inferiore presumibilmente significa il byte più basso (più basso) dei quattro byte. Quindi questo è per MS-DOS e presumibilmente può essere lasciato come zero altrimenti.

  

attributi file esterni: (4 byte)

      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.

Inoltre, il file sorgente unix / unix.c nei sorgenti per il programma zip di InfoZIP, scaricato da L'archivio di Debian contiene i seguenti commenti.

  /* 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.
   */

Quindi, tenendo tutto insieme, sembra che venga utilizzato solo il secondo byte più alto, almeno per Unix.

EDIT: ho chiesto dell'aspetto Unix di questo su Unix.SX, nella domanda " L'attributo del file esterno del formato zip " ;. Sembra che ho sbagliato un paio di cose. In particolare entrambi i primi due byte sono usati per Unix.

Guarda questo: Imposta le autorizzazioni su un file compresso in Python

Non sono del tutto sicuro se è quello che vuoi, ma sembra essere.

La linea chiave sembra essere:

zi.external_attr = 0777 << 16L

Sembra che imposta le autorizzazioni su 0777

Le risposte precedenti non funzionavano per me (su OS X 10.12). Ho scoperto che oltre ai flag eseguibili (ottale 755), devo anche impostare il "file normale" bandiera (ottale 100000). Ho trovato questo menzionato qui: https://unix.stackexchange.com/questions/ 14705 / il-zip-formati-esterni-file-attributo

Un esempio completo:

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

Un esempio completo della mia specifica base utente, la creazione di un file zip di un file .app in modo che tutto nella cartella Sommario / MacOS / sia eseguibile: https://gist.github.com/Draknek/3ce889860cea4f59838386a79cc11a85

È possibile estendere la classe ZipFile per modificare l'autorizzazione del file predefinito:

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)

Questo esempio modifica l'autorizzazione del file predefinito in 664 e mantiene 775 per le directory.

Codice correlato:

Quando lo fai in questo modo, funziona bene?

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

In caso contrario, suggerirei di inserire un os.chmod nel ciclo for con 0777 autorizzazioni come questa:

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)

Guarda anche cosa Modulo zipfile di Python :

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
    ...

`` `

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top