Reputation: 5413
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.
Upvotes: 9
Views: 10719
Reputation: 245
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
Upvotes: 2
Reputation: 90899
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()
Upvotes: 11