Tarfile / Zipfile extractall () изменяет имя файла некоторых файлов

1

Здравствуйте! В настоящее время я работаю над инструментом, который должен извлечь некоторые файлы .tar.

Он прекрасно работает по большей части, но у меня есть одна проблема:

Некоторые файлы .tar и .zip имеют имена, содержащие "недопустимые" символы (f.ex ":"). Эта программа должна работать на машинах с Windows, поэтому мне приходится иметь дело с этим.

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

Моя текущая реализация:

def read_zip(filepath, extractpath):
    with zipfile.ZipFile(filepath, 'r') as zfile:
        contains_bad_char = False
        for finfo in zfile.infolist():
            if ":" in finfo.filename:
                contains_bad_char = True
        if not contains_bad_char:
            zfile.extractall(path=extractpath)


def read_tar(filepath, extractpath):
    with tarfile.open(filepath, "r:gz") as tar:
        contains_bad_char = False
        for member in tar.getmembers():
            if ":" in member.name:
                contains_bad_char = True
        if not contains_bad_char:
            tar.extractall(path=extractpath)

Так что в настоящее время я просто игнорирую все эти результаты, что не идеально.

Чтобы лучше описать, о чем я прошу, приведу небольшой пример:

file_with_files.tar -> small_file_1.txt
                    -> small_file_2.txt
                    -> annoying:file_1.txt
                    -> annoying:file_1.txt

Следует извлечь в

file_with_files -> small_file_1.txt
                -> small_file_2.txt
                -> annoying_file_1.txt
                -> annoying_file_1.txt

Является ли единственным решением перебирать каждый файлобъект в сжатом файле и извлекать его по одному или есть более элегантное решение?

  • 0
    Вам нужно использовать библиотеку, которая позволяет вам предоставить функцию обратного вызова, которая заменит каждое «:» на «_» на лету. Например, Zip-Ada делает это, см. Compose_func @ unzip-ada.sf.net/za_html/unzip__ads.htm#85_8
Теги:
file
zip
tar

1 ответ

1
Лучший ответ

Согласно [Python 3]: ZipFile. Извлечь (член, путь = Нет, pwd = Нет):

В Windows недопустимые символы (:, <, >, |, ", ? И *) заменяются подчеркиванием (_).

Итак, все уже решено:

>>> import os
>>> import zipfile
>>>
>>> os.getcwd()
'e:\\Work\\Dev\\StackOverflow\\q055340013'
>>> os.listdir()
['arch.zip']
>>>
>>> zf = zipfile.ZipFile("arch.zip")
>>> zf.namelist()
['file0.txt', 'file:1.txt']
>>> zf.extractall()
>>> zf.close()
>>>
>>> os.listdir()
['arch.zip', 'file0.txt', 'file_1.txt']

Быстрый просмотр по tarfile (source и doc) не выявил ничего подобного (и я не был бы очень удивлен, если бы этого не было, так как формат .tar в основном используется в Nix), поэтому вам придется это сделать вручную. Все не так просто, как я ожидал, поскольку tarfile не предлагает возможность извлечения члена под другим именем, как это делает zipfile.
Во всяком случае, здесь кусок кода (у меня были zipfile и tarfile в качестве муз или источников вдохновения):

def read_tar(filepath, extractpath="."):
    win_illegal = ':<>|"?*'
    table = str.maketrans(win_illegal, '_' * len(win_illegal))
    with tarfile.open(filepath, "r:gz") as tar:
        for member in tar.getmembers():
            if member.isdir():
                os.makedirs(member.path.translate(table))
            else:
                with open(os.path.join(extractpath, member.path.translate(table)), "wb") as fout:
                    fout.write(tarfile.ExFileObject(tar, member).read())

Обратите внимание, что приведенный выше код работает для простых файлов .tar (с простыми элементами, включая каталоги), но я не проверял его на надежность.

@EDIT0:

Добавлена обработка каталогов.

@EDIT1:

Отправлено [Python.Bugs]: tarfile: обработка недопустимых символов Windows (путь) в именах членов архива.
Я не знаю, каковы будут его результаты, поскольку я представил несколько вопросов (и исправлений для них), которые были более серьезными (на моем PoV), но по разным причинам они были отклонены.

  • 0
    Ваша реализация хорошо работает для простых файлов, как указано. Если файл .tar содержит папку с именем, содержащим недопустимые символы, он не работает. Поскольку я ничего не сказал о таких случаях в своем вопросе, я отмечу этот ответ как правильный.
  • 0
    А сейчас?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню