在python中设置压缩文件的权限

时间:2008-11-11 03:40:18

标签: python zip zipfile

我的文件test.txt位于zip存档test.zip中。 test.txt上的权限在压缩时无法控制,但现在我希望它们可以进行组写操作。我正在使用Python解压缩文件,并且不想逃避到shell。

修改 这是我到目前为止所得到的:

import zipfile

z = zipfile.ZipFile('test.zip', 'w')
zi = zipfile.ZipInfo('test.txt')
zi.external_attr = 0777 << 16L
z.writestr(zi, 'FOO')
z.close()

z = zipfile.ZipFile('test.zip', 'r')
for name in z.namelist():
    newFile = open(name, "wb")
    newFile.write(z.read(name))

    newFile.close()
z.close()

这在使用2.5.1的OS X上完美运行,但它在我的主页框(Debian,Python 2.4&amp; 2.5)或使用Python 2.4的RHEL 5上不起作用。除了OS X之外,它不会出错,但也不会更改权限。有什么想法吗?另外,writestr()如何运作?我知道我在这里使用不正确。

有没有办法在没有os.chmod的情况下执行此操作(提取文件的用户在提取文件后无权使用os.chmod)?我对zip文件有完全的写入权限。

更多信息:

> ls -l test.zip
-rwxrwxrwx 1 myuser mygroup 2008-11-11 13:24 test.zip
> unzip test.zip
Archive:  test.zip
  inflating: test.txt 
> ls -l test.txt
-rw-r--r-- 1 myuser mygroup 2008-11-11 13:34 test.txt

用户提取不是myuser,而是mygroup

4 个答案:

答案 0 :(得分:4)

我遇到了类似的问题,所以这里是我的东西的代码spinet,我相信这应该有帮助。

# extract all of the zip
for file in zf.filelist:
    name = file.filename
    perm = ((file.external_attr >> 16L) & 0777)
    if name.endswith('/'):
        outfile = os.path.join(dir, name)
        os.mkdir(outfile, perm)
    else:
        outfile = os.path.join(dir, name)
        fh = os.open(outfile, os.O_CREAT | os.O_WRONLY , perm)
        os.write(fh, zf.read(name))
        os.close(fh)
    print "Extracting: " + outfile

你可能会做类似的事情,但是插入你自己的逻辑来计算你的perm值。我应该注意到我在这里使用Python 2.5,我知道与Python的zipfile支持的某些版本有一些不兼容。

答案 1 :(得分:1)

根据文档,解压缩将权限设置为unix下存储的权限。此外,不使用shell umask。您最好的办法是确保在压缩文件之前设置了权限。

由于你不能这样做,你将不得不尝试做你想做的事情(并让它在Debian下工作。)

Pythons zipfile库存在许多问题,包括将writtr的模式设置为在某些系统上写入的文件的模式,或者将zip systm设置为windows而不是unix。所以你的不一致结果可能意味着没有任何改变。

所以你可能完全没有运气。

答案 2 :(得分:1)

@Petriborg 的回答仍然相关,但要使用 Python 3,这里有一个带有必要修复的版本:

import os
import zipfile

zip_file = "/path/to/archive.zip"
out_dir = "/path/to/output"

os.makedirs(out_dir, exist_ok=True)

with zipfile.ZipFile(zip_file, "r") as zf:
    for file in zf.filelist:
        name = file.filename
        perm = ((file.external_attr >> 16) & 0o777)
        print("Extracting: " + name)
        if name.endswith("/"):
            os.mkdir(os.path.join(out_dir, name), perm)
        else:
            outfile = os.path.join(out_dir, name)
            fh = os.open(outfile, os.O_CREAT | os.O_WRONLY, perm)
            os.write(fh, zf.read(name))
            os.close(fh)

答案 3 :(得分:0)

提取到stdout(解压缩-p)并重定向到文件?如果zip中有多个文件,您可以列出zip内容,然后一次提取一个。

for n in `unzip -l test.zip | awk 'NR > 3 && NF == 4 { print $4 }'`; do unzip -p test.zip $n > $n; done

(是的,我知道你标记了这个'python':-))