zipファイルを一時ディレクトリに展開し無圧縮のzipファイルにアーカイブしなおすスクリプトです。
#!/usr/bin/env python3
#
# zipファイルを無圧縮のzipファイルに変換
#
import tempfile
import os
import zipfile
import shutil
import glob
import pathlib
import sys
def to_stored_zip(src_path):
bak_path = os.path.join(os.path.dirname(src_path), (os.path.splitext(os.path.basename(src_path))[0] + ".bak"))
shutil.copyfile(src_path, bak_path)
# テンポラリディレクトり
with tempfile.TemporaryDirectory() as dname:
print(dname)
# zipファイルから抽出
with zipfile.ZipFile(src_path) as existing_zip:
for info in existing_zip.infolist():
if not info.flag_bits & 0x800:
try:
info.filename = info.filename.encode('cp437').decode('cp932')
except:
info.filename = info.filename.encode('cp437').decode('utf-8')
if os.sep != "/" and os.sep in info.filename:
info.filename = info.filename.replace(os.sep, "/")
print(info.filename)
existing_zip.extract(info, path=dname)
# zipファイルのの削除
os.remove(src_path)
try:
# zipファイルに追加
with zipfile.ZipFile(src_path, 'w', compression=zipfile.ZIP_STORED) as new_zip:
# テンポラリディレクトリ
for fullpath in glob.glob(dname+'/**', recursive=True):
if os.path.isfile(fullpath):
p = pathlib.Path(fullpath)
name = p.relative_to(dname)
new_zip.write(fullpath, arcname=name)
except:
# 例外の場合バックアップを戻す
os.rename(bak_path, src_path)
exit(1)
# バックアップファイルの削除
os.remove(bak_path)
def to_stored_zip_usage():
print("使い方")
print("ptyhon to_stored_zip <zipファイルのパス>")
exit()
if (__name__ == "__main__"):
if (len(sys.argv) <= 1):
to_stored_zip_usage()
src_path = sys.argv[1]
to_stored_zip(src_path)
一応テストでは動きましたが、目的があれな割にファイルロストの危険がはらむ内容になっていますので、Pythonにおけるzipファイルの処理のサンプルスクリプトとお考え下さい。
Windows10での実行を想定してます。他のOSの場合ファイル名の文字コードの処理を見直す必要があります。
zipファイルは同名ファイルで変換されます。
失敗したときのために.bakでzipファイルを退避させてあります。
コメント