Извлеките файлы из zip, не сохраняя папку верхнего уровня с помощью python zipfile - PullRequest
5 голосов
/ 31 декабря 2011

Я использую текущий код для извлечения файлов из zip-файла, сохраняя при этом структуру каталогов:

zip_file = zipfile.ZipFile('archive.zip', 'r')
zip_file.extractall('/dir/to/extract/files/')
zip_file.close()

Вот структура для примера файла zip:

/dir1/file.jpg
/dir1/file1.jpg
/dir1/file2.jpg

В конце я хочу это:

/dir/to/extract/file.jpg
/dir/to/extract/file1.jpg
/dir/to/extract/file2.jpg

Но его следует игнорировать, только если в zip-файле есть папка верхнего уровня со всеми файлами внутри, поэтому при извлечении zip-файла с такой структурой:

/dir1/file.jpg
/dir1/file1.jpg
/dir1/file2.jpg
/dir2/file.txt
/file.mp3

Так и должно быть:

/dir/to/extract/dir1/file.jpg
/dir/to/extract/dir1/file1.jpg
/dir/to/extract/dir1/file2.jpg
/dir/to/extract/dir2/file.txt
/dir/to/extract/file.mp3

Есть идеи?

Ответы [ 3 ]

5 голосов
/ 01 января 2012

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

Если это так, то следующий скрипт должен делать то, что вы хотите:

import sys, os
from zipfile import ZipFile

def get_members(zip):
    parts = []
    # get all the path prefixes
    for name in zip.namelist():
        # only check files (not directories)
        if not name.endswith('/'):
            # keep list of path elements (minus filename)
            parts.append(name.split('/')[:-1])
    # now find the common path prefix (if any)
    prefix = os.path.commonprefix(parts)
    if prefix:
        # re-join the path elements
        prefix = '/'.join(prefix) + '/'
    # get the length of the common prefix
    offset = len(prefix)
    # now re-set the filenames
    for zipinfo in zip.infolist():
        name = zipinfo.filename
        # only check files (not directories)
        if len(name) > offset:
            # remove the common prefix
            zipinfo.filename = name[offset:]
            yield zipinfo

args = sys.argv[1:]

if len(args):
    zip = ZipFile(args[0])
    path = args[1] if len(args) > 1 else '.'
    zip.extractall(path, get_members(zip))
1 голос
/ 31 декабря 2011

Считайте записи, возвращенные ZipFile.namelist(), чтобы увидеть, находятся ли они в одном каталоге, а затем откройте / прочитайте каждую запись и запишите ее в файл, открытый с помощью open().

0 голосов
/ 01 января 2012

Это может быть проблема с самим zip-архивом. В приглашении Python попробуйте это, чтобы увидеть, находятся ли файлы в правильных каталогах в самом файле zip.

import zipfile

zf = zipfile.ZipFile("my_file.zip",'r')
first_file = zf.filelist[0]
print file_list.filename

Это должно сказать что-то вроде "dir1" повторите описанные выше шаги и замените индекс 1 на список файлов следующим образом: first_file = zf.filelist[1] На этот раз вывод должен выглядеть как 'dir1 / file1.jpg', если это не так, тогда файл zip не содержит каталогов и будет разархивирован для всех один каталог.

...