Exclude a directory from getting zipped using zipfile module in python
Asked Answered
L

2

9

I am trying to zip a directory using python zipfile module and its working well.But now i want to exclude some folders.ie if my director tree is like

abc
def
ghi
jkl
mno

then i want to archive all to myfile.zip but excluding "ghi"

I am trying to zip files using

zf = zipfile.ZipFile("Application server.zip", "w")
for dirname, subdirs, files in os.walk("D:\\review docs"):
    zf.write(dirname)
    for filename in files:
        zf.write(os.path.join(dirname, filename))
zf.close()

so this is archiving everything under "D:\review docs" to "Application server.zip" but i want to exclude some directories from the zip. In fact i can use linux commands to do the same but i want to use zipfile module. Also if i pop exclude folder name from "dirname" list optained from os.walk,will that work? further Adding up a check before zipping like if "dirname"=="exlude folder" will also work i think but i want a neat solution of doing the same using the module.I read some where that zipfile module provides this functionality but didn't found any code example for the same.

Lipase answered 3/8, 2015 at 4:21 Comment(0)
L
11

Yes , you can remove elements from the subdirs , that would make sure that os.walk() does not into those directories. Example -

for dirname, subdirs, files in os.walk("D:\\review docs"):
    if 'exclude directory' in subdirs:
        subdirs.remove('exclude directory')
    zf.write(dirname)
    for filename in files:
        zf.write(os.path.join(dirname, filename))
zf.close()
Lowercase answered 3/8, 2015 at 4:40 Comment(2)
This doesn't actually answer the question. How does it exclude "ghi"?Will
If you remove something from the 'subdirs' (second parameter) of os.walk() , os.walk() does not walk into it , that way that entire directory will be skipped. Details at docs.python.org/3/library/os.html#os.walkLowercase
Z
2

I wrote a more complete version, which being able to filter folders and exts

We can't simply delete the folder like .svn before zipping. The following code can help.

It zips a folder to a zip file, maintaining its structure and filtering certain folders and exts, like what you expect natually.

def IsPathValid(path, ignoreDir, ignoreExt):
    splited = None
    if os.path.isfile(path):
        if ignoreExt:
            _, ext = os.path.splitext(path)
            if ext in ignoreExt:
                return False

        splited = os.path.dirname(path).split('\\/')
    else:
        if not ignoreDir:
            return True
        splited = path.split('\\/')

    if ignoreDir:
        for s in splited:
            if s in ignoreDir:  # You can also use set.intersection or [x for],
                return False

    return True


def zipDirHelper(path, rootDir, zf, ignoreDir=None, ignoreExt=None):
    # zf is zipfile handle
    if os.path.isfile(path):
        if IsPathValid(path, ignoreDir, ignoreExt):
            relative = os.path.relpath(path, rootDir)
            zf.write(path, relative)
        return

    ls = os.listdir(path)
    for subFileOrDir in ls:
        if not IsPathValid(subFileOrDir, ignoreDir, ignoreExt):
            continue

        joinedPath = os.path.join(path, subFileOrDir)
        zipDirHelper(joinedPath, rootDir, zf, ignoreDir, ignoreExt)


def ZipDir(path, zf, ignoreDir=None, ignoreExt=None, close=False):
    rootDir = path if os.path.isdir(path) else os.path.dirname(path)

    try:
        zipDirHelper(path, rootDir, zf, ignoreDir, ignoreExt)
    finally:
        if close:
            zf.close()

use it like this:

import zipfile
theZipFile = zipfile.ZipFile(targetZipFile, 'w')
Util.ZipDir(target_dir, theZipFile, ignoreDir=[".svn"], ignoreExt=[".zip"], close=True)
# If you like to zip more files, just close=False and manually close the file or use "with xxx" on your own
Zamboanga answered 4/1, 2020 at 6:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.