如何在Python中创建目录结构的zip存档?


当前回答

此函数将递归地压缩目录树,压缩文件,并在存档中记录正确的相对文件名。存档条目与zip-r output.zip source_dir生成的条目相同。

import os
import zipfile
def make_zipfile(output_filename, source_dir):
    relroot = os.path.abspath(os.path.join(source_dir, os.pardir))
    with zipfile.ZipFile(output_filename, "w", zipfile.ZIP_DEFLATED) as zip:
        for root, dirs, files in os.walk(source_dir):
            # add directory (needed for empty dirs)
            zip.write(root, os.path.relpath(root, relroot))
            for file in files:
                filename = os.path.join(root, file)
                if os.path.isfile(filename): # regular files only
                    arcname = os.path.join(os.path.relpath(root, relroot), file)
                    zip.write(filename, arcname)

其他回答

试试下面的一个。它对我有用。

import zipfile, os
zipf = "compress.zip"  
def main():
    directory = r"Filepath"
    toZip(directory)
def toZip(directory):
    zippedHelp = zipfile.ZipFile(zipf, "w", compression=zipfile.ZIP_DEFLATED )

    list = os.listdir(directory)
    for file_list in list:
        file_name = os.path.join(directory,file_list)

        if os.path.isfile(file_name):
            print file_name
            zippedHelp.write(file_name)
        else:
            addFolderToZip(zippedHelp,file_list,directory)
            print "---------------Directory Found-----------------------"
    zippedHelp.close()

def addFolderToZip(zippedHelp,folder,directory):
    path=os.path.join(directory,folder)
    print path
    file_list=os.listdir(path)
    for file_name in file_list:
        file_path=os.path.join(path,file_name)
        if os.path.isfile(file_path):
            zippedHelp.write(file_path)
        elif os.path.isdir(file_name):
            print "------------------sub directory found--------------------"
            addFolderToZip(zippedHelp,file_name,path)


if __name__=="__main__":
    main()

要保留要归档的父目录下的文件夹层次结构,请执行以下操作:

import glob
import os
import zipfile

with zipfile.ZipFile(fp_zip, "w", zipfile.ZIP_DEFLATED) as zipf:
    for fp in glob(os.path.join(parent, "**/*")):
        base = os.path.commonpath([parent, fp])
        zipf.write(fp, arcname=fp.replace(base, ""))

如果需要,可以将其更改为使用pathlib进行文件globbing。

您可能想看看zipfile模块;文档位于http://docs.python.org/library/zipfile.html.

您可能还需要os.walk()来索引目录结构。

前面的答案完全忽略了一点,即当您在Windows上运行代码时,使用os.path.join()可以很容易地返回POSIX不兼容的路径。当使用Linux上的任何常用归档软件处理文件时,生成的归档文件将包含名称中带有反斜杠的文件,这不是您想要的。请改用path.as_posix()作为arcname参数!

import zipfile
from pathlib import Path
with zipfile.ZipFile("archive.zip", "w", zipfile.ZIP_DEFLATED) as zf:
    for path in Path("include_all_of_this_folder").rglob("*"):
        zf.write(path, path.as_posix())

正如其他人所指出的,您应该使用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, '..')))

with zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED) as zipf:
    zipdir('tmp/', zipf)