python3

Python3で特定の条件のファイルを再帰的に取得してzipにする

はじめに

jupyter notebookでデータを作成した後、PCに転送する場合、複数ファイルをzipにして送りたいことがよくあります。

pythonでzipファイルを作成したかったのですが、shutil.make_archiveを使うと.ファイルなどのゴミが入ってしまいます。
なので、必要なファイルのみフィルタできないかなと思い作成しました。

ソース

import fnmatch
import zipfile
import os

def make_filter_func(pattern_list, match):
    if type(pattern_list) == str:
        pattern_list = [pattern_list]
    if type(pattern_list) != list:
        return None

    def _filter_func(f):
        for p in pattern_list:
            if fnmatch.fnmatch(f, p):
                return match
        return not match

    return _filter_func

def get_file_tree(path, archive_list, ignore_list):
    filter_func = lambda x:True
    dfilter_func = filter_func

    if archive_list is not None:
        filter_func = make_filter_func(archive_list, True)
    elif ignore_list is not None:
        filter_func = make_filter_func(ignore_list, False)
        dfilter_func = filter_func

    for root, dirs, files in os.walk(path):
        yield from (os.path.join(root, f) for f in files if filter_func(f))
        filtered_dirs = [d for d in dirs if dfilter_func(d)]
        dirs.clear()
        dirs.extend(filtered_dirs)

def make_archive(path, archive_list=None, ignore_list='.*'):
    path_len = len(path)
    with zipfile.ZipFile(path + '.zip', 'w', compression=zipfile.ZIP_DEFLATED) as zip_f:
        for f in get_file_tree(path, archive_list, ignore_list):
            zip_f.write(f, arcname=f[path_len + 1:])

使い方

指定したディレクトリをzip化します。
デフォルトで.ファイルは無視します。

make_archive(path, archive_list, ignore_list)

path zip化したいディレクトリ名。同じディレクトリにhoge.zipを作成します。
archive_list 格納したいパターン。複数の場合はリスト指定
ignore_list 格納したくないパターン。複数の場合はリスト指定

archive_listとignore_list同時に指定した場合は、ignore_listは無視します。

ignore_listはディレクトリ名もマッチします。

よかったら使ってくださいね。