Python zipfile
モジュールで作成されたZipファイルからファイルを抽出すると、すべてのファイルが書き込み可能ではなく、読み取り専用などになります。
このファイルは、LinuxおよびPython 2.5.2で作成および抽出されています。
私が知る限り、ファイルごとにZipInfo.external_attr
プロパティを設定する必要がありますが、これはどこにでも文書化されていないようです。誰かが私を教えてくれますか?
これはうまくいくようです(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
このリンク 私がネット上で見つけた他の何よりも多くの情報があります。 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 には以下が含まれます。ここで、下位バイトはおそらく4バイトの右端(最下位)のバイトを意味します。したがって、これはMS-DOS用であり、それ以外の場合はおそらくゼロのままにすることができます。
外部ファイル属性:(4バイト)
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のアーカイブ からダウンロードされ、コメントに次のように記載されています。
/* 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では、2番目に高いバイトのみが実際に使用されているように見えます。
編集:私は、Unix.SXでのこのUnixの側面について、「 Zip形式の外部ファイル属性 」という質問で尋ねました。いくつか問題があったようです。具体的には、上位2バイトの両方がUnixに使用されます。
これを見てください: Pythonで圧縮ファイルに権限を設定してください
それがあなたの望むものかどうかは完全にはわかりませんが、そうだと思われます。
キーラインは次のように見えます。
zi.external_attr = 0777 << 16L
そこで、権限を0777
に設定しているようです。
以前の回答は私には機能しませんでした(OS X 10.12)。実行可能フラグ(8進数の755)だけでなく、「通常のファイル」フラグ(8進数の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
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
をディレクトリに保持します。
関連コード:
このようにすると、うまくいきますか?
zf = zipfile.ZipFile("something.Zip")
for name in zf.namelist():
f = open(name, 'wb')
f.write(self.read(name))
f.close()
そうでない場合は、次のような0777権限でforループに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)
Pythonのzipfileモジュール が何をするかも見てください:
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
...
`` `