Python 将多个目录压缩到一个 zip 文件中

问题描述 投票:0回答:4

我有一个顶级目录

ds237
,其下有多个子目录,如下所示:

ds237/
├── dataset_description.json
├── derivatives
├── sub-01
├── sub-02
├── sub-03
├── sub-04
├── sub-05
├── sub-06
├── sub-07
├── sub-08
├── sub-09
├── sub-10
├── sub-11
├── sub-12
├── sub-13
├── sub-21
├── sub-22
├── sub-23
├── sub-24
├── sub-25
├── sub-26
├── sub-27
├── sub-28
├── sub-29

我正在尝试根据 zip 文件的大小从 ds237 创建多个 zip 文件(具有正确的 zip 名称)。

sub01-01.zip: contain sub-01 to sub-07
sub08-13.zip : it contains sub08 to sub-13

我编写了一个创建子目录列表的逻辑

[sub-01,sub-02, sub-03, sub-04, sub-05]
。我创建了列表,以便列表中所有子目录的总大小不应> 5GB。

我的问题:是如何编写一个函数来将这些子目录(位于列表中)压缩到具有正确名称的目标zip文件中。 基本上我想写一个函数如下:

def zipit([list of subdirs], 'path/to/zipfile/sub*-*.zip'):

我在 Linux 上通常通过以下方式实现这一点:

'zip -r compress/sub01-08.zip ds237/sub-0[1-8]'
python zip archive
4个回答
14
投票

查看https://stackoverflow.com/a/1855118/375530,您可以重复使用该答案的函数将目录添加到ZipFile。

import os
import zipfile


def zipdir(path, ziph):
    # ziph is zipfile handle
    for root, dirs, files in os.walk(path):
        for file in files:
            ziph.write(os.path.join(root, file),
                       os.path.relpath(os.path.join(root, file),
                                       os.path.join(path, '..')))


def zipit(dir_list, zip_name):
    zipf = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED)
    for dir in dir_list:
        zipdir(dir, zipf)
    zipf.close()

应该使用预先分块的列表和给定名称来调用

zipit
函数。如果您想使用编程名称(例如
"path/to/zipfile/sub{}-{}.zip".format(start, end)
),您可以使用字符串格式。


1
投票

您可以使用 subprocess 调用“zip”并将路径作为参数传递


1
投票

以下将为您提供带有第一个文件夹的 zip 文件

ds100

import os
import zipfile    

def zipit(folders, zip_filename):
    zip_file = zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED)

    for folder in folders:
        for dirpath, dirnames, filenames in os.walk(folder):
            for filename in filenames:
                zip_file.write(
                    os.path.join(dirpath, filename),
                    os.path.relpath(os.path.join(dirpath, filename), os.path.join(folders[0], '../..')))

    zip_file.close()


folders = [
    "/Users/aba/ds100/sub-01",
    "/Users/aba/ds100/sub-02",
    "/Users/aba/ds100/sub-03",
    "/Users/aba/ds100/sub-04",
    "/Users/aba/ds100/sub-05"]

zipit(folders, "/Users/aba/ds100/sub01-05.zip")

例如

sub01-05.zip
的结构类似于:

ds100
├── sub-01
|   ├── 1
|       ├── 2
|   ├── 1
|   ├── 2
├── sub-02
    ├── 1
        ├── 2
    ├── 1
    ├── 2

0
投票

要批量压缩,从之前的答案改进,您可以使用以下

import os
from zipfile import ZipFile, ZIP_DEFLATED

base_dir = "."
base_zip_dir = f"{base_dir}/zip"
target_dir = f"{base_dir}/data"
folders_per_zip = 500

os.makedirs(base_zip_dir, exist_ok=True)

def zipdir(path, ziph):
    for root, _, files in os.walk(path):
        for file in files:
            ziph.write(os.path.join(root, file),
                       os.path.relpath(os.path.join(root, file), os.path.join(path, '..')))

def batch_zip(folder_list, folders_per_zip, target_dir):
    for i, folders in enumerate(zip(*[iter(folder_list)] * folders_per_zip), start=1):
        zip_filename = f"{target_dir}/{i}.zip"
        with ZipFile(zip_filename, 'w', ZIP_DEFLATED) as zipf:
            for folder in folders:
                if any(os.path.isfile(os.path.join(folder, f)) for f in os.listdir(folder)):
                    zipdir(folder, zipf)
        print(f"Zip file {zip_filename} created.")

folders = [f.path for f in os.scandir(target_dir) if f.is_dir()]
batch_zip(folders , folders_per_zip, base_zip_dir)
© www.soinside.com 2019 - 2024. All rights reserved.