zipfile, tarfile
Zipなどの圧縮・展開用モジュール
7-Zip, WinRARなどの高速なアーカイバがインストール済なら、敢えてこれを使わなくてもsubprocess.run()でそちらを使った方が速いかも。
ただ、圧縮・展開にちょっと細かい条件をつけたい時には重宝。
Zip展開:新しいもののみ上書き
- 展開先に同名の既存ファイルがあれば、更新時刻を比較し、新しければ上書き、同じか古ければスキップ
- zipには、各ファイルの更新時刻が記録されている
from zipfile import ZipFile src_path = 'src.zip' tgt_dir = 'C:\\dst' with ZipFile(src_path, mode='r') as zh: for zipinfo in zh.infolist(): # zipアーカイブ内のファイルの更新時刻を取得 zip_mtime = datetime.datetime(*zipinfo.date_time).timestamp() tgt_path = os.path.join(tgt_dir, zipinfo.filename) if os.path.exists(tgt_path): # 既存のファイルがあれば更新時刻を取得 tgt_mtime = os.path.getmtime(tgt_path) # 既存の方が新しかったらスキップ if tgt_mtime >= zip_mtime: # 一応、ファイルサイズも出力しとく tgt_size = os.path.getsize(tgt_path) zip_size = zipinfo.file_size print(zipinfo.filename, 'already exists newer one.', tgt_mtime, zip_mtime, tgt_size, zip_size) continue # 展開 zh.extract(zipinfo, tgt_dir) # ファイル更新時刻とアクセス時刻を更新(そのままだと、展開時の時刻になる) os.utime(tgt_path, (zip_mtime, zip_mtime)) print(zipinfo.filename, 'extracted.')
tgz展開: ファイル名などで選択して解凍
tarfile.open()
で圧縮ファイルを読み込み開始- modeは
r
にしとけば、tar, tgz, tbzあたりは自動判定してくれる
TarFile.getmembers()
で、圧縮ファイル中のファイルとディレクトリのTarInfo
オブジェクトをイテレートTarInfo
オブジェクトは、name, size, mtime, isfile, isdir
あたりの情報を持ってる- 解凍したいのがあったら、
TarFile.extractfile(TarInfo)
で そのファイルのio.BufferedReader
オブジェクトが得られる - 解凍したい場所にバイナリ書き込みで
open()
して書き込む
""" tgzやtbzから、.dbファイルだけを解凍して抽出 """ import tarfile import os gzip_path = 'tmp.tgz' tgt_dir = 'extract' def make_parent_dirs(path): pardir = os.path.dirname(path) if not os.path.exists(pardir): os.makedirs(pardir) def main(): if not os.path.exists(tgt_dir): os.makedirs(tgt_dir) with tarfile.open(gzip_path, mode='r') as rh: for mem in rh.getmembers(): spn = mem.name.split('/') if spn[-1][-3:] != '.db': continue # print(mem) tgt_path = os.path.join(tgt_dir, mem.name) make_parent_dirs(tgt_path) with open(tgt_path, mode='wb') as wh: wh.write(rh.extractfile(mem).read()) if __name__ == '__main__': main()