Pythonで指定フォルダ配下のサブフォルダとファイルを全てZIP圧縮する方法


postal-bike

photo credit: kohlmann.sascha Postboten via photopin (license)

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

プログラミング初心者&Windowsユーザー向けにPythonでZIP圧縮するツールの作り方をお伝えしています。

前回の記事はこちら。

Pythonでフォルダ内のサブフォルダ&ファイルを全てリストアップする方法
初心者向け&Windowsユーザー向けPythonでZIP圧縮をするツールの作り方をお伝えしています。今回はPythonでフォルダ内のツリー構造を走査してサブフォルダとファイルを全てリストアップする方法です。

Pythonでフォルダ配下のツリーを渡り歩くos.walk関数の使い方についてお伝えしました。

さて、今回ですが、そのos.walk関数を使うことで、フォルダ配下のツリー上にあるすべてのサブフォルダとファイルについてZIPファイルに追加して圧縮することができます。

ということで、Pythonで指定のフォルダ配下をまとめてZIP圧縮するツールの作り方です。

では、行ってみましょう!

スポンサーリンク

複数のフォルダとファイルをZIP圧縮する

単体のZIP圧縮についておさらい

まず、ZIP圧縮についておさらいですが、前々回作ったスクリプトが参考になります。

こちらです。

import zipfile
with zipfile.ZipFile('test.zip','w') as myzip:
     myzip.write('test.csv')

ZipFile関数を使って、test.zipというZIPファイルを作成して、そこにwriteメソッドを使ってtest.csvという単体のファイルを追加するという内容です。

前々回の記事もご参考下さい。

初心者でも簡単!PythonでファイルをZIP形式に圧縮する基本のプログラム
プログラミング初心者かつWindowsユーザー向けに、Pythonでいろんな便利ツールを作る方法をお伝えしています。今回はPythonでファイルをZIP形式に圧縮するプログラムの作り方をお伝えします。

複数のフォルダとファイルを直接追加するスクリプト

単体ではなくて複数、そしてファイルだけでなく、フォルダも追加したい場合は以下のようなスクリプトを作ればOKです。

import os, zipfile
with zipfile.ZipFile('test.zip','w') as myzip:
    myzip.write('test')
    myzip.write('test\\test1')
    myzip.write('test\\test1\\test1.csv')
    myzip.write('test\\test2')
    myzip.write('test\\test2\\test2-1.csv')
    myzip.write('test\\test2\\test2-2.csv')
    myzip.write('test\\test.csv')

実行するとZIPファイルが生成され、中身をのぞくと以下のようになります。

PythonでZIP圧縮したフォルダの中身

writeメソッドでフォルダやファイルを追加していき、ZIPファイルがクローズした(with文のブロックを抜けた)時点で、追加されたフォルダ・ファイルを含んだ形でZIPファイルが生成されます。

ですが、全部のサブフォルダとファイルを直接指定するわけにはいきませんよね。

フォルダ配下の全てのフォルダ・ファイルをZIPファイルに追加

os.walk関数のおさらい

ということで、前回ご紹介したos.walk関数が活躍します。

前回のスクリプトを復習してみましょう。

import os
for folder, subfolders, files in os.walk('test'):
    print('folder: {}'.format(folder))
    print('subfolders: {}'.format(subfolders))
    print('files: {}'.format(files))
    print()

os.walk関数は指定したフォルダをルートとして、配下のツリーに含まれるすべてのフォルダについて、以下のタプルを生成します。

(folder, subfolders, files)

folderはフォルダ、subfoldersはそのフォルダに含まれるサブフォルダのリスト、filesはそのフォルダに含まれるファイルのリストです。

os.walk関数を使ったフォルダの圧縮

つまり、os.walk関数で生成したタプルについて

  • folder
  • filesに含まれるファイル

をZIPファイルに追加すれば、ルートフォルダ配下の全てのフォルダとファイルについてZIPファイルに追加できるということです。

それを踏まえて、以下スクリプトを作成してみました。

import os, zipfile
with zipfile.ZipFile('test.zip','w') as myzip:
    for folder, subfolders, files in os.walk('test'):
        myzip.write(folder)
        for file in files:
            myzip.write(file)

しかし、このスクリプトでは以下のようなエラーが出てしまいます。

Pythonで出たFileNotFoundError

FileNotFoundError: [WinError 2] 指定されたファイルが見つかりません。: ‘test.csv’

なぜエラーが出てしまうかというと、リストfilesの要素はファイル名しか持たずに、フォルダパスの情報を持っていないんですね。

該当のファイルは作業フォルダの中には存在しませんので、「ファイルが見つかりません。」となってしまうわけです。

つまり、「test\test2」と、作業フォルダからのパスも含めて指定をしてあげる必要があります。

os.path.join関数を使ってパスを結合する

作業フォルダからのパスは、folderがその情報を持っていますので、folderとfileを連結すればこの問題は解決します。

ですから、前述のスクリプトの6行目を

myzip.write(folder + "\\" + file)

とすればOK!…というわけではあるのですが、せっかくなのでパスの結合にはos.path.join関数を使いましょうか。

なぜなら、os.path.join関数ならWindowsでもMacでも環境の違いを気にせずに、賢くパスを結合してくれるのです。

os.path.join(パス1, パス2,…)

これで、指定したパスを全て環境に合わせたファイルセパレータを用いて連結してパスを生成します。

ということで、完成したスクリプトはこちらです。

import os, zipfile
with zipfile.ZipFile('test.zip','w') as myzip:
    for folder, subfolders, files in os.walk('test'):
        myzip.write(folder)
        for file in files:
            myzip.write(os.path.join(folder,file))

まとめ

以上、Pythonで指定のフォルダ配下をフォルダ、ファイル含めて全てZIP圧縮する方法をお伝えしました。

逐一または定期的にZIP圧縮するフォルダがあれば、仕込んでおかない手はないですよね。

さて、次回ですが、ZIPファイル名に「年月日」を付与する方法をお伝えします。

Pythonで現在の日時を取得して指定のフォーマットの文字列に変換する
プログラミング初心者&Windowsユーザー向けにPythonでフォルダ圧縮ツールを作る方法をお伝えしています。今回はPythonで現在の日時を取得して文字列に変換する方法についてお伝えします。

どうぞお楽しみに!

連載目次:初心者向け!PythonでファイルをZIP圧縮するツールを作る

複数ファイルをまとめてZIPに圧縮すると、メール添付やバックアップなどに便利です。定期的にZIP圧縮をする必要があるのであれば、Pythonに任せてしまいましょう!ツールの作り方をシリーズでお伝えしていきます。
  1. 初心者でも簡単!PythonでファイルをZIP形式に圧縮する基本のプログラム
  2. Pythonでフォルダ内のサブフォルダ&ファイルを全てリストアップする方法
  3. Pythonで指定フォルダ配下のサブフォルダとファイルを全てZIP圧縮する方法
  4. Pythonで現在の日時を取得して指定のフォーマットの文字列に変換する

タイトルとURLをコピーしました