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?
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
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.
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à.
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
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)