Python 指定フォルダ内にある指定拡張子の全ファイルを指定フォルダにコピーする

# '20/02/29更新:コードの可読性を良くしました。
本記事のデータ処理内容を示します。例えば、下図のようにフォルダが複数あり、各フォルダにはデータファイルが格納されている。ちなみに、本プログラムは「pgm.py」で保存場所はどこでも構わない。

f:id:HK29:20190501004753j:plain

例えば「D:\python\日付\test\dataA」の中には複数の種類の拡張子のファイルが多数ある(下図)。

f:id:HK29:20190501004900j:plain

本プログラムを実行すると、例えば、拡張子jpgのみを下図のようにフォルダ「D:\python\日付\data_190501\dir_jpg\dataA」へコピーする。

f:id:HK29:20190501010203j:plain

本プログラムの実行例を示す。

例:$ python pgm.py jpg ./dataA

引数は二つあり、一つ目に抽出したいファイルの拡張子、二つ目に抽出したいフォルダパスを指定する。下図は実行例4つです。コピー先フォルダがすでに存在する場合は上書きしない仕様(下図4つ目)。

f:id:HK29:20190501011437j:plain

▼本プログラム
コピー先親フォルダ名と場所を変更したい場合は、下から4行目にある「new_dirpath」に指定すれば良い。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, os
import shutil

import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d")

### コピー先フォルダがあれば終了。無ければ作成する関数
def check_dir(new_dirpath, check_file):
    # コピー先の親フォルダの存在有無の確認
    if os.path.isdir(new_dirpath):
        pass
    else:
        os.mkdir(new_dirpath)

    # コピー先のサブフォルダの存在有無の確認
    new_sub_dirpath_list = [new_dirpath, 'dir_' + check_file]
    new_sub_dirpath = os.path.join(*new_sub_dirpath_list)
    if os.path.isdir(new_sub_dirpath):
        print(new_sub_dirpath + " already exists")
        exit("exit")
    else:
        os.mkdir(new_sub_dirpath)

    return new_sub_dirpath

### 指定フォルダ内を再帰的に探索し、指定拡張子があった場合にファイルをコピーする関数
def copy_files(check_dirpath, check_file, new_sub_dirpath):
    if not os.path.isdir(check_dirpath): # コピー元フォルダがない場合に強制終了する
        print("not found " + check_dirpath)
        exit("exit")
    else:
        for dirpath, dirnames, filenames in os.walk(check_dirpath): # 再帰的にフォルダ探索
            for file in filenames:
                filepath = os.path.join(dirpath, file)
                if file.endswith(check_file): # ファイルの拡張子を確認しマッチすれば処理する
                    shutil.copy2(filepath, new_sub_dirpath) # ファイルをコピーする
                    new_file_path = os.path.join(new_sub_dirpath, file)
                    print("copied -> ", new_file_path)

def main():
    # コピー先フォルダがあれば終了。無ければ作成する関数
    new_sub_dirpath = check_dir(new_dirpath, check_file)
    # 指定フォルダ内を再帰的に探索し、指定拡張子があった場合にファイルをコピーする関数
    copy_files(check_dirpath, check_file, new_sub_dirpath)

if __name__ == '__main__':
    check_file = sys.argv[1]   #example jpg
    check_dirpath = sys.argv[2]   #example ./dataA
    
    new_dirpath = "../data_" + now # カレントフォルダのひとつ上にコピー先フォルダを作成する
    
    main()

以上