zipfile, tarfile
Zipなどの圧縮・展開用モジュール
7-Zip, WinRARなどの高速なアーカイバがインストール済なら、敢えてこれを使わなくてもsubprocess.run()でそちらを使った方が速いかも。
ただ、圧縮・展開にちょっと細かい条件をつけたい時には重宝。
Zip展開:新しいもののみ上書き
- 展開先に同名の既存ファイルがあれば、更新時刻を比較し、新しければ上書き、同じか古ければスキップ
- zipには、各ファイルの更新時刻が記録されている
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
from zipfile import ZipFilesrc_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()して書き込む
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
"""tgzやtbzから、.dbファイルだけを解凍して抽出"""import tarfileimport osgzip_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() |

