Перезаписать существующие файлы только для чтения при использовании tar-файла Python - PullRequest
10 голосов
/ 30 августа 2011

Я пытаюсь использовать модуль tarfile Python для извлечения архива tar.gz.

Я бы хотел, чтобы при извлечении были перезаписаны все целевые файлы, если они уже существуют - это нормальное поведение tarfile.*

Тем не менее, я пытаюсь уловить, что некоторые файлы имеют защиту от записи (например, chmod 550).

Операция tarfile.extractall() фактически не выполняется:

IOError: [Errno 13] Permission denied '/foo/bar/file'

Если я пытаюсь удалить файлы из обычной командной строки, я могу это сделать, мне просто нужно ответить на приглашение:

$ rm <filename>
rm: <filename>: override protection 550 (yes/no)? yes

Обычная утилита GNU tar также легко обрабатывает эти файлы - онапросто перезаписывает их при извлечении.

Мой пользователь является владельцем файлов, поэтому не составит труда рекурсивно изменить целевые файлы перед запуском tarfile.extractall.Или я могу использовать shutil.rmtree, чтобы забить цель заранее, это обходной путь, который я использую сейчас ... Однако, это выглядит немного хакерским.

Есть ли более Pythonic способ перезаписи ручного чтения -только файлы в tarfile, использующие исключения или что-то подобное?

Ответы [ 2 ]

8 голосов
/ 30 августа 2011

Вы можете зацикливаться на элементах tarball и извлекать / обрабатывать ошибки для каждого файла:

В современной версии Python я бы использовал оператор with:

import os, tarfile

with tarfile.TarFile('myfile.tar', 'r', errorlevel=1) as tar:
    for file_ in tar:
        try:
            tar.extract(file_)
        except IOError as e:
            os.remove(file_.name)
            tar.extract(file_)
        finally:
            os.chmod(file_.name, file_.mode)

Если вы не можете использовать with, просто замените блок операторов with на:

tarball = tarfile.open('myfile.tar', 'r', errorlevel=1)
for file_ in tar:

Если ваш tar-шар сжат, есть быстрый способ справиться с этим просто:

tarfile.open('myfile.tar.gz', 'r:gz')

Было бы лучше, если бы у tarfile.extractall была опция перезаписи.

1 голос
/ 19 июня 2012

Мне удалось заставить код Майка Стедера работать так:

tarball = tarfile.open(filename, 'r:gz')
for f in tarball:
    try: 
        tarball.extract(f)
    except IOError as e:
        os.remove(f.name)
        tarball.extract(f)
    finally:
        os.chmod(f.name, f.mode)
...