Comment définir les permissions (attributs) sur un fichier dans un fichier ZIP en utilisant le module zipfile de Python?

lorsque j'extrait des fichiers à partir d'un fichier ZIP créé avec le module zipfile de Python, tous les fichiers ne sont pas disponibles en écriture, en lecture seule, etc.

le fichier est créé et extrait sous Linux et Python 2.5.2.

comme je peux le dire, j'ai besoin de définir la propriété ZipInfo.external_attr pour chaque fichier, mais cela ne semble pas être documenté où que ce soit que je puisse trouver, quelqu'un peut-il m'éclairer?

34
demandé sur Martin Prikryl 2009-01-12 09:51:27

5 réponses

cela semble fonctionner (merci Evan, de le mettre ici pour que la ligne soit en contexte):

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

j'aimerais encore voir quelque chose qui documente cela... Une autre ressource que j'ai trouvée était une note sur le format de fichier Zip: http://www.pkware.com/documents/casestudies/APPNOTE.TXT

36
répondu Tom 2013-06-13 23:28:18

ce lien contient plus d'information que tout ce que j'ai pu trouver sur le net. Même la source zip n'a rien. Copier la section pertinente pour la postérité. Ce patch n'est pas vraiment sur la documentation de ce format, qui va juste pour montrer comment pathétique (lire inexistante) la documentation actuelle est.

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

aussi, ce lien a le suivant. Ici, l'octet de poids faible signifie probablement le plus à droite (la plus faible) octet de quatre octets. Si celui-ci est pour MS-DOS et peut sans doute être laissé à zéro sinon.

attributs pour les fichiers externes: (4 octets)

      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.

aussi, le fichier source unix/unix.c dans les sources du programme zip D'InfoZIP, téléchargées à partir de les archives de Debian contiennent les commentaires suivants.

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

Donc, en prenant tout cela ensemble, il on dirait que seul le deuxième octet le plus élevé est réellement utilisé, au moins pour Unix.

EDIT: j'ai posé des questions sur L'aspect Unix de ceci sur Unix.SX, dans la question " l'attribut de fichier externe du format zip ". On dirait que je suis un couple de choses mal. Plus précisément, les deux premiers octets sont utilisés pour Unix.

20
répondu Faheem Mitha 2017-04-13 12:36:24

Regardez ceci: définissez les permissions sur un fichier compressé en python

je ne suis pas entièrement sûr si c'est ce que vous voulez, mais il semble être.

la ligne clé semble être:

zi.external_attr = 0777 << 16L

on dirait qu'il fixe les permissions à 0777 là.

12
répondu Evan Fosmark 2017-05-23 12:09:49

les réponses précédentes n'ont pas fonctionné pour moi (sur OS X 10.12). J'ai trouvé qu'en plus des options exécutables (octal 755), je dois aussi mettre l'option "regular file" (octal 100000). J'ai trouvé ceci mentionné ici: https://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute

un exemple complet:

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 exemple complet de mon usecase spécifique, créant un zip d'a.application de sorte que tout dans le dossier Contents/MacOS/ est exécutable: https://gist.github.com/Draknek/3ce889860cea4f59838386a79cc11a85

6
répondu Alan Hazelden 2018-01-25 04:03:35

quand tu le fais comme ça, ça marche bien?

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

sinon, je suggère de lancer un os.chmod dans la boucle for avec les permissions 0777 comme ceci:

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)
0
répondu Evan Fosmark 2009-01-12 07:15:11