708

Python でディレクトリ構造の zip アーカイブを作成するにはどうすればよいですか?

4

27 に答える 27

1748

最も簡単な方法は、 を使用することshutil.make_archiveです。zip 形式と tar 形式の両方をサポートしています。

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

zipfileディレクトリ全体を圧縮するよりも複雑なことをする必要がある場合 (特定のファイルをスキップするなど)、他の人が提案したようにモジュールを掘り下げる必要があります。

于 2014-09-03T17:26:41.437 に答える
658

他の人が指摘したように、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, '..')))
      
zipf = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
zipdir('tmp/', zipf)
zipf.close()
于 2009-12-06T11:23:55.163 に答える
78

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()
于 2009-12-06T11:28:24.663 に答える
58

Python でディレクトリ構造の zip アーカイブを作成するにはどうすればよいですか?

Python スクリプトで

Python 2.7+ ではshutilmake_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_dirbase_dir、親ディレクトリ内のファイルは . までアーカイブされますroot_dir

Cygwin 2.7 でこれをテストする際に問題がありました。cwd の root_dir 引数が必要です。

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

シェルからの Python の使用

zipfileモジュールを使用して、シェルからPythonでこれを行うことができます:

$ python -m zipfile -c zipname sourcedir

wherezipnameは目的の宛先ファイルの名前 (必要に応じて追加.zipしますが、自動的には追加されません) であり、sourcedir はディレクトリへのパスです。

Python を圧縮する (または単に親ディレクトリを必要としない):

と を使用して python パッケージを圧縮しようとして__init__.py__main__.pyて、親ディレクトリが必要ない場合は、

$ python -m zipfile -c zipname sourcedir/*

$ python zipname

パッケージを実行します。(zip アーカイブからのエントリ ポイントとしてサブパッケージを実行できないことに注意してください。)

Python アプリの圧縮:

Python3.5+ を使用していて、特に Python パッケージを圧縮したい場合は、 zipapp を使用します

$ python -m zipapp myapp
$ python myapp.pyz
于 2016-03-31T18:57:20.383 に答える
24

Python 標準ライブラリ セットの一部である shutil を使用します。shutil の使用はとても簡単です (以下のコードを参照):

  • 第 1 引数: 結果の zip/tar ファイルのファイル名、
  • 2 番目の引数: zip/tar、
  • 3 番目の引数: dir_name

コード:

import shutil
shutil.make_archive('/home/user/Desktop/Filename','zip','/home/username/Desktop/Directory')
于 2018-10-12T09:46:46.227 に答える
12

結果の zip ファイルに圧縮を追加するには、このリンクを確認してください。

変更する必要があります:

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

zip = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
于 2013-04-27T17:14:02.897 に答える
5

Mark Byers から提供されたコードにいくつかの変更を加えました。以下の関数は、空のディレクトリがある場合はそれらも追加します。例は、zip に追加されたパスが何であるかをより明確にする必要があります。

#!/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

于 2013-06-10T09:28:26.360 に答える
3

python3、pathlib、および zipfile を使用して、役立つ別のコード例があります。どのOSでも動作するはずです。

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!')
于 2015-10-02T10:03:14.890 に答える
2

一般的なグラフィカル ファイル マネージャーの圧縮フォルダーのような機能が必要な場合は、次のコードを使用できます。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()
于 2016-03-21T13:40:10.027 に答える
1

zipfileおそらくモジュールを見たいと思うでしょう。http://docs.python.org/library/zipfile.htmlにドキュメントがあります。

os.walk()ディレクトリ構造のインデックスを作成することもできます。

于 2009-12-06T11:17:50.930 に答える
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 )
于 2014-07-30T23:13:20.930 に答える
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()
于 2015-04-23T11:18:16.770 に答える
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)
于 2018-09-25T13:32:32.100 に答える
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))
于 2016-12-14T21:50:12.490 に答える
0

Reimund と Morten Zilmer のコメント (相対パスと空のディレクトリを含む) を使用して、Mark Byers のソリューションを統合した関数を用意しました。ベスト プラクティスとして、withZipFile のファイル構成で使用されます。

この関数は、zip されたディレクトリ名と「.zip」拡張子を持つデフォルトの zip ファイル名も準備します。したがって、1 つの引数のみで動作します: 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)))
于 2016-12-24T20:32:56.153 に答える