Подтвердить что ты не робот

Создать .zip в Python?

Я пытаюсь создать функцию в моем script, которая застегивает содержимое данного исходного каталога (src) в zip файл (dst). Например, zip('/path/to/dir', '/path/to/file.zip'), где /path/to/dir - это каталог, а /path/to/file.zip еще не существует. Я не хочу заархивировать саму директорию, это делает всю разницу в моем случае. Я хочу заархивировать файлы (и поддиры) в каталоге. Это то, что я пытаюсь:

def zip(src, dst):
    zf = zipfile.ZipFile("%s.zip" % (dst), "w")
    for dirname, subdirs, files in os.walk(src):
        zf.write(dirname)
        for filename in files:
            zf.write(os.path.join(dirname, filename))
    zf.close()

Это создает почтовый индекс, по существу /. Например, если я zipped /path/to/dir, извлечение zip создает каталог с "path" в нем, с "to" в этом каталоге и т.д.

Есть ли у кого-нибудь функция, которая не вызывает этой проблемы?

Я не могу это подчеркнуть, ему требуется, чтобы zip файлы в каталоге, а не сама directoy.

4b9b3361

Ответ 1

Метод zipfile.write() принимает необязательный аргумент arcname который указывает, что имя файла должно находиться внутри zip файла.

Вы можете использовать это, чтобы удалить путь до src в начале. Здесь я используйте os.path.abspath(), чтобы убедиться, что как src, так и filename, возвращаемое os.walk(), имеет общий префикс.

#!/usr/bin/env python2.7

import os
import zipfile

def zip(src, dst):
    zf = zipfile.ZipFile("%s.zip" % (dst), "w", zipfile.ZIP_DEFLATED)
    abs_src = os.path.abspath(src)
    for dirname, subdirs, files in os.walk(src):
        for filename in files:
            absname = os.path.abspath(os.path.join(dirname, filename))
            arcname = absname[len(abs_src) + 1:]
            print 'zipping %s as %s' % (os.path.join(dirname, filename),
                                        arcname)
            zf.write(absname, arcname)
    zf.close()

zip("src", "dst")

С такой структурой каталогов:

src
└── a
    ├── b
    │   └── bar
    └── foo

script печатает:

zipping src/a/foo as a/foo
zipping src/a/b/bar as a/b/bar

И содержимое результирующего zip файла:

Archive:  dst.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  01-28-13 11:36   a/foo
        0  01-28-13 11:36   a/b/bar
 --------                   -------
        0                   2 files

Ответ 2

Используйте параметр arcname, чтобы управлять именем/путем в zip файле.

Например, для zip файла, содержащего только файлы, нет каталогов:

zf.write(os.path.join(dirname, filename), arcname=filename)

Или создать новый каталог внутри zip файла:

zf.write(os.path.join(dirname, filename), arcname=os.path.join("my_zip_dir", filename))

Ответ 3

Из того, что я могу сказать, вы близки. Вы можете использовать dirname и basename, чтобы убедиться, что вы захватываете правильное имя пути:

>>> os.path.dirname("/path/to/dst")
'/path/to'
>>> os.path.basename("/path/to/dst")
'dst'

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

def zip(src, dst):
    parent = os.path.dirname(dst)
    folder = os.path.basename(dst)

    os.chdir(parent):
    for dirname, subdirs, filenames in os.walk(folder):
        ...

Это создает:

dst/a.txt
dst/b
dst/b/c.txt
...etc...

Если вы не хотите включать имя "dst", вы можете просто сделать os.chdir(dst), а затем os.walk('.').

Надеюсь, что это поможет.