如何创build目录的zip存档
如何在Python中创build一个目录结构的zip压缩文件?
正如其他人指出的,你应该使用zipfile 。 该文档告诉你哪些function可用,但并没有真正解释如何使用它们来压缩整个目录。 我认为用一些示例代码来解释是最简单的:
#!/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/
最简单的方法是使用shutil.make_archive 。 它支持zip和tar格式。
import shutil shutil.make_archive(output_filename, 'zip', dir_name)
如果你需要做一些比压缩整个目录更复杂的东西(比如跳过某些文件),那么你需要像其他人一样深入研究zipfile模块。
要将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()
此函数将recursion地压缩目录树, 压缩文件,并在归档中logging正确的相对文件名。 存档条目与zip -r output.zip source_dir
生成的条目相同。
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)
如何在Python中创build一个目录结构的zip压缩文件?
在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
的文件,但仍将父级文件中的文件归档到root_dir
。
我有一个问题在2.7上testingCygwin – 它想要一个root_dir参数,为cwd:
make_archive('zipfile_name', 'zip', root_dir='.')
从shell中使用Python
您也可以使用zipfile
模块从shell中使用Python执行此操作:
$ python -m zipfile -c zipname sourcedir
其中, zipname
是所需目标文件的名称(如果需要,可以添加.zip
,不会自动执行),sourcedir是目录的path。
压缩Python(或只是不希望父目录):
如果你想用__init__.py
和__main__.py
压缩一个python包,而你不想要父目录,那么
$ python -m zipfile -c zipname sourcedir/*
和
$ python zipname
会运行包。 (请注意,不能将子包作为压缩归档的入口点运行。)
压缩一个Python应用程序:
如果你有python3.5 +,并且特别想压缩一个Python包,使用zipapp :
$ python -m zipapp myapp $ python myapp.pyz
要将压缩文件添加到生成的压缩文件中,请查看此链接 。
你需要改变:
zip = zipfile.ZipFile('Python.zip', 'w')
至
zip = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
我对Mark Byers给出的代码做了一些修改。 下面的函数也会添加空目录,如果你有它们。 示例应该更清楚地说明添加到zip中的path是什么。
#!/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)
以上是一个简单的function,应该适用于简单的情况。 你可以在我的Gist中find更优雅的课程: https : //gist.github.com/Eccenux/17526123107ca0ac28e6
我有另一个代码示例,可以帮助,使用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!')
你可能想看看zipfile
模块; 在http://docs.python.org/library/zipfile.html有文档。;
你也可能想要os.walk()
来索引目录结构。
下面是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 )
尝试下面的一个,为我工作 。
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()
使用基本的Python zipfile模块 。
如果您想要像任何常见graphics文件pipe理器的压缩文件夹的function,您可以使用下面的代码,它使用zipfile模块。 使用这段代码,你将得到带有path作为其根文件夹的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()
这是一个现代的方法,使用pathlib和一个上下文pipe理器。 将文件直接放在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))
我通过将Mark Byers的解决scheme与Reimund和Morten Zilmer的评论(相对path和包括空目录)整合起来,准备了一个function。 作为一个最佳实践,用于ZipFile的文件构build。
该函数还准备了压缩目录名称和“.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)))
现代Python(3.6+)使用pathlib
模块进行简洁的类OOP处理path,使用pathlib.Path.rglob()
进行recursion通配。 据我所知,这相当于乔治五赖利的回答:压缩拉链,最顶层的元素是一个目录,保留空的目录,使用相对path。
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))
注意:如可选types提示所示, zip_name
不能是Path对象( 将在3.6.2+中修复 )。
# 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))