Установить разрешения для сжатого файла в python

У меня есть файл test.txt, который находится внутри zip-архива test.zip. Разрешения на test.txt находятся вне моего контроля, когда он сжат, но теперь я хочу, чтобы они были доступны для групповой записи. Я извлекаю файл с помощью Python и не хочу убегать в оболочку.

EDIT: Вот что у меня есть:

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

Это отлично работает в OS X с использованием 2.5.1, но не работает на моем домашнем компьютере (Debian, Python 2.4 и 2.5) или на RHEL 5 с Python 2.4. Во всем, кроме 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.


person Harley Holcombe    schedule 11.11.2008    source источник
comment
Другая вещь, которую вы могли бы сделать, это подробно рассказать о своих проблемах в Linux, так как кто-то здесь может помочь, но вы ничего не дали для продолжения.   -  person John Fouhy    schedule 11.11.2008
comment
Не уверен, что вы имеете в виду. Linux ведет себя нормально, хотя python ведет себя по-другому на OS X.   -  person Harley Holcombe    schedule 11.11.2008
comment
Ну, вы сказали, что это работает на OS X, а не на Debian. Если бы вы сказали, почему это не работает, возможно, выложили какой-то код или сообщения об ошибках, кто-то мог бы помочь. Просто мысль.   -  person John Fouhy    schedule 11.11.2008
comment
Ах, я понимаю, что вы имеете в виду. Мозг сегодня не работает должным образом.   -  person Harley Holcombe    schedule 11.11.2008
comment
Пользователь может разархивировать, но не может os.chmod? звучит странно.   -  person orip    schedule 14.11.2008
comment
Да, они могут записывать в каталог, но файл внутри zip-архива не доступен для групповой записи. Это странная ситуация.   -  person Harley Holcombe    schedule 17.11.2008


Ответы (4)


У меня была такая же проблема, как и у вас, поэтому вот код спинета из моих материалов, я считаю, что он должен помочь здесь.

# 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

Вы можете сделать что-то подобное, но вставьте свою собственную логику для расчета значения проницаемости. Я должен отметить, что здесь я использую Python 2.5, я знаю о нескольких несовместимостях с некоторыми версиями поддержки zip-файлов Python.

person Petriborg    schedule 27.02.2009

Согласно документации, unzip устанавливает разрешения для тех, которые хранятся в unix. Также не используется оболочка umask. Лучше всего убедиться, что права доступа установлены до того, как вы заархивируете файл.

Поскольку вы не можете этого сделать, вам придется попытаться сделать то, что вы пытались сделать (и заставить это работать в Debian).

Был ряд проблем с библиотекой zipfile Python, в том числе установка режима writestr для файла, записываемого в некоторых системах, или установка системы zip на windows вместо unix. Таким образом, ваши противоречивые результаты могут означать, что ничего не изменилось.

Так что вам может совсем не повезти.

person Chris    schedule 11.11.2008

Ответ @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)
person Mike T    schedule 31.03.2021

Извлечь в стандартный вывод (распаковать -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

(да, я знаю, что вы отметили этого «питона» :-))

person John Fouhy    schedule 11.11.2008