จะสร้างไฟล์ zip ของไดเร็กตอรี่ใน Python ได้อย่างไร?


491

ฉันจะสร้างไฟล์ zip ของโครงสร้างไดเรกทอรีใน Python ได้อย่างไร


21
อย่าใช้โซลูชันที่แนะนำในคำตอบที่ได้รับการยอมรับ แต่ควรใช้make_archiveจากshutil(ถ้าคุณต้องการซิปไดเรกทอรีเดียวซ้ำ)
malana

คำตอบ:


526

เป็นคนอื่นได้ชี้ให้เห็นคุณควรใช้zipfile เอกสารอธิบายถึงฟังก์ชั่นที่ใช้งานได้ แต่ไม่ได้อธิบายว่าคุณสามารถใช้ฟังก์ชันเหล่านี้ในการบีบอัดทั้งไดเร็กทอรีได้อย่างไร ฉันคิดว่ามันอธิบายได้ง่ายที่สุดด้วยรหัสตัวอย่าง:

#!/usr/bin/env python
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))

if __name__ == '__main__':
    zipf = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
    zipdir('tmp/', zipf)
    zipf.close()

ดัดแปลงมาจาก: http://www.devshed.com/c/a/Python/Python-UnZipped/


129
os.path.relpath(os.path.join(root, file), os.path.join(path, '..'))ฉันจะเพิ่มอาร์กิวเมนต์ที่สองเพื่อเรียกร้องการเขียนผ่าน ซึ่งจะช่วยให้คุณบีบอัดไดเรกทอรีจากไดเรกทอรีทำงานใด ๆ โดยไม่ได้รับเส้นทางที่สมบูรณ์แบบในที่เก็บถาวร
Reimund

8
มีเรื่องตลกเกิดขึ้นอีกเมื่อฉันพยายาม zip โฟลเดอร์และส่งผลลัพธ์ zip ไปยังโฟลเดอร์เดียวกัน :-)
การพนัน Sibbs

13
shutilทำให้มันง่ายจริงๆในเพียงบรรทัดเดียว โปรดตรวจสอบคำตอบด้านล่าง ..
droidlabour

7
คุณอาจสนใจโดยทำ ziph.write (os.path.join (path, file), arcname = file) เพื่อให้ชื่อไฟล์ในไฟล์เก็บถาวรไม่สัมพันธ์กับฮาร์ดไดรฟ์
Christophe Blin

1
อ๊ะฉันไม่ได้รับ.close()สาย!
information_interchange

1062

shutil.make_archiveวิธีที่ง่ายที่สุดคือการใช้งาน รองรับรูปแบบ zip และ tar

import shutil
shutil.make_archive(output_filename, 'zip', dir_name)

หากคุณต้องการทำสิ่งที่ซับซ้อนกว่าการซิปไดเรกทอรีทั้งหมด (เช่นการข้ามไฟล์บางไฟล์) คุณจะต้องขุดลงในzipfileโมดูลตามที่คนอื่นแนะนำ


113
shutilเป็นส่วนหนึ่งของไลบรารีหลามมาตรฐาน นี่ควรเป็นคำตอบที่ดีที่สุด
AlexG

4
นี่คือคำตอบที่รัดกุมที่สุดที่นี่และยังมีข้อได้เปรียบในการเพิ่มไดเรกทอรีย่อยและไฟล์ทั้งหมดลงในไฟล์เก็บถาวรโดยตรงแทนที่จะมีทุกอย่างที่รวมอยู่ในโฟลเดอร์ระดับบนสุด (ซึ่งส่งผลให้มีระดับซ้ำซ้อนในโครงสร้างโฟลเดอร์
aitch-hat

3
@cmcginty คุณช่วยกรุณาเจาะจงให้มากขึ้นได้ไหมว่ามันไม่ปลอดภัยสำหรับเธรด? การรันหลายเธรดในขณะที่เรียกใช้สิ่งนี้จะทำให้ล่ามเสียหายหรือไม่
std''OrgnlDave

13
ถูกเตือนว่าก่อนหน้า Python 3.4, shutil.make_archive ไม่สนับสนุน ZIP64 และจะล้มเหลวในการสร้างไฟล์ ZIP ที่ใหญ่กว่า 2GB
azdev

2
@Teekin เลขที่ถ้าคุณดูที่ข้อบกพร่องรายงาน (bugs.python.org/issue30511) คุณจะเห็นว่าการใช้งานshutil.make_archive os.chdir()จากสิ่งที่ฉันอ่านเกี่ยวกับos.chdir()มันทำงานทั่วโลก
Sam Malayek

65

ในการเพิ่มเนื้อหาของmydirectoryไปยังไฟล์ zip ใหม่รวมถึงไฟล์และไดเรกทอรีย่อยทั้งหมด:

import os
import zipfile

zf = zipfile.ZipFile("myzipfile.zip", "w")
for dirname, subdirs, files in os.walk("mydirectory"):
    zf.write(dirname)
    for filename in files:
        zf.write(os.path.join(dirname, filename))
zf.close()

สำหรับฉันรหัสนี้โยนด้านล่างข้อผิดพลาด TypeError: ไฟล์ที่ไม่ถูกต้อง: <zipfile.ZipFile [ปิด]>
Nishad Up

10
คุณใช้withแทนการไม่ต้องโทรหาclose()ตัวเองได้ไหม?
ArtOfWarfare

50

ฉันจะสร้างไฟล์ zip ของโครงสร้างไดเรกทอรีใน Python ได้อย่างไร

ในสคริปต์ Python

ใน Python 2.7+ shutilมีmake_archiveฟังก์ชั่น

from shutil import make_archive
make_archive(
  'zipfile_name', 
  'zip',           # the archive format - or tar, bztar, gztar 
  root_dir=None,   # root for archive - current working dir if None
  base_dir=None)   # start archiving from here - cwd if None too

zipfile_name.zipที่นี่เก็บซิปจะมีชื่อ ถ้าbase_dirจะลงไกลออกไปจากroot_dirมันจะแยกไฟล์ไม่ได้อยู่ในbase_dirแต่ยังคงเก็บไฟล์ใน dirs root_dirผู้ปกครองขึ้นไป

ฉันมีปัญหาในการทดสอบนี้ใน Cygwin ด้วย 2.7 - มันต้องการอาร์กิวเมนต์ root_dir สำหรับ cwd:

make_archive('zipfile_name', 'zip', root_dir='.')

ใช้ Python จากเชลล์

คุณสามารถทำได้ด้วย Python จากเชลล์โดยใช้zipfileโมดูล:

$ python -m zipfile -c zipname sourcedir

zipnameชื่อไฟล์ปลายทางที่คุณต้องการอยู่ที่ไหน(เพิ่ม.zipถ้าคุณต้องการมันจะไม่ทำมันโดยอัตโนมัติ) และ sourcedir เป็นพา ธ ไปยังไดเรกทอรี

การบีบอัด Python (หรือเพียงแค่ไม่ต้องการ dir หลัก):

หากคุณกำลังพยายามบีบอัดแพ็กเกจหลามด้วย a __init__.pyและ__main__.pyและคุณไม่ต้องการให้ dir หลักมันเป็นเช่นนั้น

$ python -m zipfile -c zipname sourcedir/*

และ

$ python zipname

จะเรียกใช้แพคเกจ (โปรดทราบว่าคุณไม่สามารถเรียกใช้แพคเกจย่อยเป็นจุดเริ่มต้นจากที่เก็บถาวรแบบซิปได้)

การซิปแอพ Python:

หากคุณมี python3.5 + และต้องการแพ็กเกจ Python แบบพิเศษให้ใช้zipapp :

$ python -m zipapp myapp
$ python myapp.pyz

32

ฟังก์ชั่นนี้จะซิปแผนผังไดเรกทอรีซ้ำซ้ำ บีบอัดไฟล์และบันทึกชื่อไฟล์ที่ถูกต้องในไฟล์เก็บถาวร 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)

17

ใช้ shutil ซึ่งเป็นส่วนหนึ่งของชุดไลบรารีมาตรฐานของหลาม การใช้ shutil นั้นง่ายมาก (ดูรหัสด้านล่าง):

  • 1st arg: ชื่อไฟล์ของผลลัพธ์ไฟล์ zip / tar
  • 2nd arg: zip / tar,
  • ARG ที่ 3: dir_name

รหัส:

import shutil
shutil.make_archive('/home/user/Desktop/Filename','zip','/home/username/Desktop/Directory')

12

สำหรับการเพิ่มการบีบอัดลงในไฟล์ zip ที่เป็นผลลัพธ์ให้ดูที่ลิงค์นี้

คุณต้องเปลี่ยน:

zip = zipfile.ZipFile('Python.zip', 'w')

ถึง

zip = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)

5

ผมได้ทำการเปลี่ยนแปลงบางอย่างเพื่อให้รหัสที่กำหนดโดยมาร์คยอร์ส ฟังก์ชั่นด้านล่างจะเพิ่มไดเรกทอรีว่างถ้าคุณมี ตัวอย่างควรทำให้ชัดเจนยิ่งขึ้นว่ามีการเพิ่มพา ธ ไปยังไฟล์ซิปอะไร

#!/usr/bin/env python
import os
import zipfile

def addDirToZip(zipHandle, path, basePath=""):
    """
    Adding directory given by \a path to opened zip file \a zipHandle

    @param basePath path that will be removed from \a path when adding to archive

    Examples:
        # add whole "dir" to "test.zip" (when you open "test.zip" you will see only "dir")
        zipHandle = zipfile.ZipFile('test.zip', 'w')
        addDirToZip(zipHandle, 'dir')
        zipHandle.close()

        # add contents of "dir" to "test.zip" (when you open "test.zip" you will see only it's contents)
        zipHandle = zipfile.ZipFile('test.zip', 'w')
        addDirToZip(zipHandle, 'dir', 'dir')
        zipHandle.close()

        # add contents of "dir/subdir" to "test.zip" (when you open "test.zip" you will see only contents of "subdir")
        zipHandle = zipfile.ZipFile('test.zip', 'w')
        addDirToZip(zipHandle, 'dir/subdir', 'dir/subdir')
        zipHandle.close()

        # add whole "dir/subdir" to "test.zip" (when you open "test.zip" you will see only "subdir")
        zipHandle = zipfile.ZipFile('test.zip', 'w')
        addDirToZip(zipHandle, 'dir/subdir', 'dir')
        zipHandle.close()

        # add whole "dir/subdir" with full path to "test.zip" (when you open "test.zip" you will see only "dir" and inside it only "subdir")
        zipHandle = zipfile.ZipFile('test.zip', 'w')
        addDirToZip(zipHandle, 'dir/subdir')
        zipHandle.close()

        # add whole "dir" and "otherDir" (with full path) to "test.zip" (when you open "test.zip" you will see only "dir" and "otherDir")
        zipHandle = zipfile.ZipFile('test.zip', 'w')
        addDirToZip(zipHandle, 'dir')
        addDirToZip(zipHandle, 'otherDir')
        zipHandle.close()
    """
    basePath = basePath.rstrip("\\/") + ""
    basePath = basePath.rstrip("\\/")
    for root, dirs, files in os.walk(path):
        # add dir itself (needed for empty dirs
        zipHandle.write(os.path.join(root, "."))
        # add files
        for file in files:
            filePath = os.path.join(root, file)
            inZipPath = filePath.replace(basePath, "", 1).lstrip("\\/")
            #print filePath + " , " + inZipPath
            zipHandle.write(filePath, inZipPath)

ด้านบนเป็นฟังก์ชั่นพื้นฐานที่ควรใช้กับกรณีง่าย ๆ คุณสามารถค้นหาคลาสที่หรูหรากว่าใน Gist ของฉัน: https://gist.github.com/Eccenux/17526123107ca0ac28e6


1
การจัดการเส้นทางที่อาจจะง่ายมากโดยใช้os.path ดูคำตอบของฉัน
George V. Reilly

ข้อผิดพลาด: zipHandle.write (os.path.join (root, ".")) ไม่ได้พิจารณา basePath
Petter

ใช่คุณพูดถูก ฉันได้ปรับปรุงในภายหลังนี้เล็กน้อย ;-) gist.github.com/Eccenux/17526123107ca0ac28e6
Nux

4

Python สมัยใหม่ (3.6+) โดยใช้pathlibโมดูลสำหรับการจัดการเส้นทางที่เหมือนกับ OOP และpathlib.Path.rglob()สำหรับการวนซ้ำแบบซ้ำ เท่าที่ฉันสามารถบอกได้สิ่งนี้เทียบเท่ากับคำตอบของ George V. Reilly: รหัสไปรษณีย์ที่มีการบีบอัดองค์ประกอบอันดับต้น ๆ คือไดเรกทอรีเก็บ dirs ที่ว่างเปล่าใช้เส้นทางที่สัมพันธ์กัน

from pathlib import Path
from zipfile import ZIP_DEFLATED, ZipFile

from os import PathLike
from typing import Union


def zip_dir(zip_name: str, source_dir: Union[str, PathLike]):
    src_path = Path(source_dir).expanduser().resolve(strict=True)
    with ZipFile(zip_name, 'w', ZIP_DEFLATED) as zf:
        for file in src_path.rglob('*'):
            zf.write(file, file.relative_to(src_path.parent))

หมายเหตุ: ตามคำแนะนำประเภทที่เป็นตัวเลือกบ่งบอกว่าzip_nameไม่สามารถเป็นวัตถุเส้นทาง ( จะได้รับการแก้ไขใน 3.6.2+ )


1
Fantastic! กระชับ! ทันสมัย!
ingyhere

3

ฉันมีตัวอย่างรหัสอื่นที่อาจช่วยได้โดยใช้ python3, pathlib และ zipfile มันควรจะทำงานในระบบปฏิบัติการใด ๆ

from pathlib import Path
import zipfile
from datetime import datetime

DATE_FORMAT = '%y%m%d'


def date_str():
    """returns the today string year, month, day"""
    return '{}'.format(datetime.now().strftime(DATE_FORMAT))


def zip_name(path):
    """returns the zip filename as string"""
    cur_dir = Path(path).resolve()
    parent_dir = cur_dir.parents[0]
    zip_filename = '{}/{}_{}.zip'.format(parent_dir, cur_dir.name, date_str())
    p_zip = Path(zip_filename)
    n = 1
    while p_zip.exists():
        zip_filename = ('{}/{}_{}_{}.zip'.format(parent_dir, cur_dir.name,
                                             date_str(), n))
        p_zip = Path(zip_filename)
        n += 1
    return zip_filename


def all_files(path):
    """iterator returns all files and folders from path as absolute path string
    """
    for child in Path(path).iterdir():
        yield str(child)
        if child.is_dir():
            for grand_child in all_files(str(child)):
                yield str(Path(grand_child))


def zip_dir(path):
    """generate a zip"""
    zip_filename = zip_name(path)
    zip_file = zipfile.ZipFile(zip_filename, 'w')
    print('create:', zip_filename)
    for file in all_files(path):
        print('adding... ', file)
        zip_file.write(file)
    zip_file.close()


if __name__ == '__main__':
    zip_dir('.')
    print('end!')

1

คุณอาจต้องการดูzipfileโมดูล มีเอกสารที่http://docs.python.org/library/zipfile.html

คุณอาจต้องการจัดos.walk()ทำดัชนีโครงสร้างไดเรกทอรี


1

นี่คือความแตกต่างของคำตอบที่ Nux ให้กับฉัน:

def WriteDirectoryToZipFile( zipHandle, srcPath, zipLocalPath = "", zipOperation = zipfile.ZIP_DEFLATED ):
    basePath = os.path.split( srcPath )[ 0 ]
    for root, dirs, files in os.walk( srcPath ):
        p = os.path.join( zipLocalPath, root [ ( len( basePath ) + 1 ) : ] )
        # add dir
        zipHandle.write( root, p, zipOperation )
        # add files
        for f in files:
            filePath = os.path.join( root, f )
            fileInZipPath = os.path.join( p, f )
            zipHandle.write( filePath, fileInZipPath, zipOperation )

1

ลองด้านล่างหนึ่งมันทำงานให้ฉัน

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()

1

หากคุณต้องการฟังก์ชั่นเช่นโฟลเดอร์บีบอัดของเครื่องมือจัดการไฟล์กราฟิกทั่วไปที่คุณสามารถใช้รหัสต่อไปนี้ก็ใช้โมดูลzipfile ใช้รหัสนี้คุณจะมีไฟล์ zip ที่มีพา ธ เป็นโฟลเดอร์รูท

import os
import zipfile

def zipdir(path, ziph):
    # Iterate all the directories and files
    for root, dirs, files in os.walk(path):
        # Create a prefix variable with the folder structure inside the path folder. 
        # So if a file is at the path directory will be at the root directory of the zip file
        # so the prefix will be empty. If the file belongs to a containing folder of path folder 
        # then the prefix will be that folder.
        if root.replace(path,'') == '':
                prefix = ''
        else:
                # Keep the folder structure after the path folder, append a '/' at the end 
                # and remome the first character, if it is a '/' in order to have a path like 
                # folder1/folder2/file.txt
                prefix = root.replace(path, '') + '/'
                if (prefix[0] == '/'):
                        prefix = prefix[1:]
        for filename in files:
                actual_file_path = root + '/' + filename
                zipped_file_path = prefix + filename
                zipf.write( actual_file_path, zipped_file_path)


zipf = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
zipdir('/tmp/justtest/', zipf)
zipf.close()

1

เพื่อเพิ่มความยืดหยุ่นเช่นเลือกไดเรกทอรี / ไฟล์ตามการใช้ชื่อ:

import os
import zipfile

def zipall(ob, path, rel=""):
    basename = os.path.basename(path)
    if os.path.isdir(path):
        if rel == "":
            rel = basename
        ob.write(path, os.path.join(rel))
        for root, dirs, files in os.walk(path):
            for d in dirs:
                zipall(ob, os.path.join(root, d), os.path.join(rel, d))
            for f in files:
                ob.write(os.path.join(root, f), os.path.join(rel, f))
            break
    elif os.path.isfile(path):
        ob.write(path, os.path.join(rel, basename))
    else:
        pass

สำหรับแผนผังไฟล์:

.
├── dir
   ├── dir2
      └── file2.txt
   ├── dir3
      └── file3.txt
   └── file.txt
├── dir4
   ├── dir5
   └── file4.txt
├── listdir.zip
├── main.py
├── root.txt
└── selective.zip

คุณสามารถเลือกได้อย่างเดียวdir4และroot.txt:

cwd = os.getcwd()
files = [os.path.join(cwd, f) for f in ['dir4', 'root.txt']]

with zipfile.ZipFile("selective.zip", "w" ) as myzip:
    for f in files:
        zipall(myzip, f)

หรือเพียงแค่listdirในไดเรกทอรีการเรียกใช้สคริปต์และเพิ่มทุกอย่างจากที่นั่น:

with zipfile.ZipFile("listdir.zip", "w" ) as myzip:
    for f in os.listdir():
        if f == "listdir.zip":
            # Creating a listdir.zip in the same directory
            # will include listdir.zip inside itself, beware of this
            continue
        zipall(myzip, f)

รหัสไปรษณีย์นี้ แต่ไม่บีบอัด
Alex

1

สมมติว่าคุณต้องการซิปโฟลเดอร์ทั้งหมด (ไดเรกทอรีย่อย) ในไดเรกทอรีปัจจุบัน

for root, dirs, files in os.walk("."):
    for sub_dir in dirs:
        zip_you_want = sub_dir+".zip"
        zip_process = zipfile.ZipFile(zip_you_want, "w", zipfile.ZIP_DEFLATED)
        zip_process.write(file_you_want_to_include)
        zip_process.close()

        print("Successfully zipped directory: {sub_dir}".format(sub_dir=sub_dir))

1

สำหรับวิธีการกระชับลำดับชั้นของโฟลเดอร์ภายใต้ไดเรกทอรีหลักที่จะเก็บถาวร:

import glob
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


1

คำตอบมากมายที่นี่และฉันหวังว่าฉันอาจมีส่วนร่วมกับรุ่นของฉันเองซึ่งจะขึ้นอยู่กับคำตอบเดิม (โดยวิธีการ) แต่ด้วยมุมมองแบบกราฟิกมากขึ้นนอกจากนี้ยังใช้บริบทสำหรับแต่ละ zipfileการติดตั้งและการเรียงลำดับos.walk()ในการสั่งซื้อที่จะมี สั่งเอาท์พุท

มีโฟลเดอร์เหล่านี้และไฟล์ (ในโฟลเดอร์อื่น ๆ ) ฉันต้องการสร้าง.zipสำหรับแต่ละcap_โฟลเดอร์:

$ tree -d
.
├── cap_01
|    ├── 0101000001.json
|    ├── 0101000002.json
|    ├── 0101000003.json
|
├── cap_02
|    ├── 0201000001.json
|    ├── 0201000002.json
|    ├── 0201001003.json
|
├── cap_03
|    ├── 0301000001.json
|    ├── 0301000002.json
|    ├── 0301000003.json
| 
├── docs
|    ├── map.txt
|    ├── main_data.xml
|
├── core_files
     ├── core_master
     ├── core_slave

นี่คือสิ่งที่ฉันใช้กับความคิดเห็นเพื่อทำความเข้าใจกระบวนการ

$ cat zip_cap_dirs.py 
""" Zip 'cap_*' directories. """           
import os                                                                       
import zipfile as zf                                                            


for root, dirs, files in sorted(os.walk('.')):                                                                                               
    if 'cap_' in root:                                                          
        print(f"Compressing: {root}")                                           
        # Defining .zip name, according to Capítulo.                            
        cap_dir_zip = '{}.zip'.format(root)                                     
        # Opening zipfile context for current root dir.                         
        with zf.ZipFile(cap_dir_zip, 'w', zf.ZIP_DEFLATED) as new_zip:          
            # Iterating over os.walk list of files for the current root dir.    
            for f in files:                                                     
                # Defining relative path to files from current root dir.        
                f_path = os.path.join(root, f)                                  
                # Writing the file on the .zip file of the context              
                new_zip.write(f_path) 

โดยทั่วไปสำหรับการวนซ้ำแต่ละครั้งos.walk(path)ฉันกำลังเปิดบริบทสำหรับzipfileการตั้งค่าและหลังจากนั้นการวนซ้ำซ้ำfilesซึ่งเป็นlistไฟล์จากrootไดเรกทอรีสร้างเส้นทางสัมพัทธ์สำหรับแต่ละไฟล์ตามกระแสrootไดเรกทอรีผนวกกับzipfileบริบทที่กำลังทำงานอยู่ .

และผลลัพธ์จะถูกนำเสนอเช่นนี้:

$ python3 zip_cap_dirs.py
Compressing: ./cap_01
Compressing: ./cap_02
Compressing: ./cap_03

หากต้องการดูเนื้อหาของแต่ละ.zipไดเรกทอรีคุณสามารถใช้lessคำสั่ง:

$ less cap_01.zip

Archive:  cap_01.zip
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
  22017  Defl:N     2471  89% 2019-09-05 08:05 7a3b5ec6  cap_01/0101000001.json
  21998  Defl:N     2471  89% 2019-09-05 08:05 155bece7  cap_01/0101000002.json
  23236  Defl:N     2573  89% 2019-09-05 08:05 55fced20  cap_01/0101000003.json
--------          ------- ---                           -------
  67251             7515  89%                            3 files

0

นี่คือวิธีการที่ทันสมัยโดยใช้ pathlib และตัวจัดการบริบท วางไฟล์ใน zip โดยตรงแทนที่จะอยู่ในโฟลเดอร์ย่อย

def zip_dir(filename: str, dir_to_zip: pathlib.Path):
    with zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
        # Use glob instead of iterdir(), to cover all subdirectories.
        for directory in dir_to_zip.glob('**'):
            for file in directory.iterdir():
                if not file.is_file():
                    continue
                # Strip the first component, so we don't create an uneeded subdirectory
                # containing everything.
                zip_path = pathlib.Path(*file.parts[1:])
                # Use a string, since zipfile doesn't support pathlib  directly.
                zipf.write(str(file), str(zip_path))

0

ฉันเตรียมฟังก์ชั่นโดยรวมโซลูชันของ Mark Byers กับข้อคิดเห็นของ Reimund และ Morten Zilmer (เส้นทางสัมพัทธ์และรวมถึงไดเรกทอรีว่าง) เป็นการปฏิบัติที่ดีที่สุดwithใช้ในการสร้างไฟล์ของ ZipFile

ฟังก์ชั่นนี้ยังเตรียมชื่อไฟล์ซิปเริ่มต้นด้วยชื่อไดเรกทอรีซิปและส่วนขยาย '.zip' ดังนั้นจึงใช้งานได้กับอาร์กิวเมนต์เดียวเท่านั้น: ไดเรกทอรีต้นทางที่จะซิป

import os
import zipfile

def zip_dir(path_dir, path_file_zip=''):
if not path_file_zip:
    path_file_zip = os.path.join(
        os.path.dirname(path_dir), os.path.basename(path_dir)+'.zip')
with zipfile.ZipFile(path_file_zip, 'wb', zipfile.ZIP_DEFLATED) as zip_file:
    for root, dirs, files in os.walk(path_dir):
        for file_or_dir in files + dirs:
            zip_file.write(
                os.path.join(root, file_or_dir),
                os.path.relpath(os.path.join(root, file_or_dir),
                                os.path.join(path_dir, os.path.pardir)))

0
# import required python modules
# You have to install zipfile package using pip install

import os,zipfile

# Change the directory where you want your new zip file to be

os.chdir('Type your destination')

# Create a new zipfile ( I called it myfile )

zf = zipfile.ZipFile('myfile.zip','w')

# os.walk gives a directory tree. Access the files using a for loop

for dirnames,folders,files in os.walk('Type your directory'):
    zf.write('Type your Directory')
    for file in files:
        zf.write(os.path.join('Type your directory',file))

0

หลังจากอ่านคำแนะนำแล้วฉันก็พบวิธีคล้ายกับที่ทำงานกับ 2.7.x โดยไม่ต้องสร้างชื่อไดเรกทอรี "ตลก" (ชื่อคล้ายสัมบูรณ์) และจะสร้างโฟลเดอร์ที่ระบุเฉพาะภายใน zip

หรือในกรณีที่คุณต้องการให้ zip ของคุณมีโฟลเดอร์ด้านในพร้อมเนื้อหาของไดเรกทอรีที่เลือก

def zipDir( path, ziph ) :
 """
 Inserts directory (path) into zipfile instance (ziph)
 """
 for root, dirs, files in os.walk( path ) :
  for file in files :
   ziph.write( os.path.join( root, file ) , os.path.basename( os.path.normpath( path ) ) + "\\" + file )

def makeZip( pathToFolder ) :
 """
 Creates a zip file with the specified folder
 """
 zipf = zipfile.ZipFile( pathToFolder + 'file.zip', 'w', zipfile.ZIP_DEFLATED )
 zipDir( pathToFolder, zipf )
 zipf.close()
 print( "Zip file saved to: " + pathToFolder)

makeZip( "c:\\path\\to\\folder\\to\\insert\\into\\zipfile" )

0

ฟังก์ชั่นเพื่อสร้างไฟล์ซิป

def CREATEZIPFILE(zipname, path):
    #function to create a zip file
    #Parameters: zipname - name of the zip file; path - name of folder/file to be put in zip file

    zipf = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
    zipf.setpassword(b"password") #if you want to set password to zipfile

    #checks if the path is file or directory
    if os.path.isdir(path):
        for files in os.listdir(path):
            zipf.write(os.path.join(path, files), files)

    elif os.path.isfile(path):
        zipf.write(os.path.join(path), path)
    zipf.close()

โปรดอธิบายด้วยตัวอย่างเพื่อที่ฉันจะสามารถแก้ไขคำตอบของฉันได้
#:

อย่างไรก็ตาม zipfile "ขณะนี้ยังไม่สามารถสร้างแฟ้มที่เข้ารหัสลับ" (จากdocs.python.org/3.9/library/zipfile.html )
เฟรด

0

ใช้zipfly

import zipfly

paths = [
    {
        'fs': '/path/to/large/file'
    },
]

zfly = zipfly.ZipFly( paths = paths )

with open("large.zip", "wb") as f:
    for i in zfly.generator():
        f.write(i)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.