みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
プログラミング初心者&Windowsユーザー向けにPythonでZIP圧縮するツールの作り方をお伝えしています。
前回の記事はこちら。
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という単体のファイルを追加するという内容です。
前々回の記事もご参考下さい。
複数のフォルダとファイルを直接追加するスクリプト
単体ではなくて複数、そしてファイルだけでなく、フォルダも追加したい場合は以下のようなスクリプトを作れば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ファイルが生成され、中身をのぞくと以下のようになります。
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はそのフォルダに含まれるファイルのリストです。
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)
しかし、このスクリプトでは以下のようなエラーが出てしまいます。
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でも環境の違いを気にせずに、賢くパスを結合してくれるのです。
これで、指定したパスを全て環境に合わせたファイルセパレータを用いて連結してパスを生成します。
ということで、完成したスクリプトはこちらです。
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ファイル名に「年月日」を付与する方法をお伝えします。
どうぞお楽しみに!