Tex, python, illusrator, VPSの学生ノート

latotex-blog

Python

【Windows】複数のzipファイル(それぞれ中身はPDF1つのみ)を一度に解凍する方法

投稿日:2020年6月14日 更新日:







Zip形式は送る方にとっては便利ですが、受け取る方は解凍や削除の処理が面倒くさいですよね。(特に複数Zipファイルが送られてきたときは!)
私も受講する予定の講義のシラバス(PDF形式)をダウンロードするのですが、
システムの問題なのか、ダウンロードするとご丁寧に1つずつZIP形式にして送られてきます・・
大した数ではないのですがやはり面倒くさいのでPythonに任せることにしました。
Jupyter Notebook + windows10で作業しています。

スポンサーリンク

Pythonコード

ベースとしては、こちらのサイト様のコードを採用させていただきました。

#!/usr/bin/env python3

#必要なものを宣言
import os
from zipfile import ZipFile
import glob

#ZIPをダウンロードした場所
folder0 = r"C:\Users\user\Downloads"

#解凍した中身を入れるフォルダー
#すでにあるフォルダーと被らないような名前を設定してください
#この例では「C:\Users\user\Downloads\box」というフォルダーを設定しています。
folder1 = folder0 + "\\box"

#folder0まで移動
os.chdir(folder0)

#folder1をつくる
os.makedirs(folder1, exist_ok=True)

#folder0の中にあるzip形式のファイルの一覧を取得
zip_files = glob.glob("*.zip")

#Zipファイルの解凍
for file in zip_files:
    with ZipFile(file) as zp:
        zp.extractall(folder1)

    #解凍したファイルを削除
    os.remove(file)

注意してほしいこと

ポイントはファイルのパス指定とファイル作成です!

folder0 = r"C:\Users\user\Downloads"
folder1 = folder0 + "\\box"
os.makedirs(folder1, exist_ok=True)

folder0にある「r」は地味に重要です。これをつけないと(unicode error)が発生してしまいます。なぜなら、pythonにおける「/」は他の意味に捉えられてしまうからです。(ex.文字列中で/nをつかうとprintしたときに/nの後の文章が改行されてしまうなど)folder1にある「\\」も「r」と同じです。windowsのパスを指定する際は「\\」か「r」を使いましょう。

os.makedirs(folder1, exist_ok=True)はエラー対策用と言ってもいいかもしれません。exist_ok=Trueは、すでに同じファイル名があったときも新しいフォルダーを作るという命令です。os.makedirsはデフォルトでは既に存在するフォルダー名を指定することができないので、exist_ok=Trueを指定することでエラーを直して再度実行したとき、「フォルダーは既に存在しています」というエラーを避けることができます!
folder1のコメントアウトに「すでにあるフォルダーと被らないような名前を設定してください」と書いたのは既にあるフォルダーに上書きされてしまうのを防ぐためです。

解凍したファイル名が文字化けした場合(追記 2021/04/08)

ファイル名がすべて英語の場合は問題ないですが、日本語の場合はファイル名が文字化けします。ありがたいことに解決方法が以下のサイトに載っていました!

この解決方法をもとにPythonコードをforループがある箇所から書き直します。

for file in zip_files:
    with ZipFile(file) as zp:

        #infolistオブジェクトから解凍するファイル名を取得する
        for info in zp.infolist():

            #エンコーディングして文字列に戻す
            #(詳しくは「https://qiita.com/tohka383/items/b72970b295cbc4baf5ab」を参照)
            info.filename = info.orig_filename.encode('cp437').decode('cp932')
            if os.sep != "/" and os.sep in info.filename:
                info.filename = info.filename.replace(os.sep, "/")

            #Zipファイルの解凍(extractallからextractに変更)
            zp.extract(info, folder1)

    #元のzipファイルを削除
    os.remove(file)

参考にしたサイト様

os.makedirsについて
https://note.nkmk.me/python-os-mkdir-makedirs/

なぜwindowsのファイル名のパスにrをつける必要があるのか

https://ja.stackoverflow.com/questions/11582/

globってなに?
https://techacademy.jp/magazine/18928

-Python

Copyright© latotex-blog , 2021 All Rights Reserved Powered by STINGER.