LoginSignup
6
9

More than 1 year has passed since last update.

フォルダと拡張子を指定してフォルダ内のファイルを別の1つのフォルダにコピー

Last updated at Posted at 2021-07-31

はじめに

サーバーに存在するサブフォルダを含む大量のファイルをローカルの1つのフォルダにダウンロード(コピー)して処理したい時が割とある。
フォルダごとに同一名のファイルが存在する場合はコピーする際に上書きされる可能性がある。
また、フォルダのデータ全てをコピーするのではなく、特定の拡張子のファイルだけコピーしたい場合が結構ある。
そんな課題を解決するためのGUIを作成した。

仕様

cpygui.png

・上下2つの「フォルダを選択」ボタンで「コピー元フォルダ(1行目)」と「コピー先フォルダ(2行目)」を選択する。
・3行目にコピー対象の拡張子を「.」抜きで入力する※最大5つ
・「実行ボタン」でコピー処理が実行される
・コピー先のファイル名はコピー元のディレクトリを起点とした相対パスのパス文字がアンダーバーに変換された名前が付けられる

コード

import PySimpleGUI as sg
import os
import re, shutil
import pathlib

INPUT_BOX_SIZE = 5
HEADER_ROW = 1
INI_EXT_LINE = 2
MAX_NUM_EXT = 5

#### 関数
# ファイル名変換関数
def name_savefile_dirname(path ,org_dir):
    file_path = path.replace('/', os.sep) #パスの区切り文字を統一
    org_path = pathlib.Path(org_dir)
    sub_path = pathlib.Path(file_path)
    file_name = sub_path.relative_to(org_path) # 指定ディレクトリ基準のファイルの相対パスを取得
    return str(file_name).replace("\\","_") #パスの区切り文字をアンダーバーに変換

# ファイルコピー関数
def copy_files(org_dir, save_dir, target_ext):
    file_list = [] #コピーするファイルのリスト
    filepath_list = [] #コピーするファイルパスのリスト
    for dirpath, dirnames, filenames in os.walk(org_dir): #コピー元のディレクトリを基準にtarget_extで指定した拡張子のファイルをリスト化
        for file in filenames:
            for ext in target_ext:
                m = re.search(re.escape(ext), file) #指定した拡張子のファイルを探す
                if m :
                    file_list.append(file) #ファイル名をリストに追加
                    filepath_list.append(os.path.join(dirpath, file)) #コピー元ファイルのパスをリストに追加

    for i in range(len(file_list)):
        save_file_path = os.path.join(save_dir, name_savefile_dirname(filepath_list[i], org_dir)) #コピー先ディレクトリ名とコピー元ディレクトリを付けたファイル名を結合
        shutil.copy2(filepath_list[i], save_file_path) #ファイルをコピー
        print(save_file_path)

#### GUI
#  セクション1 - オプションの設定と標準レイアウト
sg.theme('Dark Blue 3')

layout = [
    #1行目
    [sg.InputText('コピー元フォルダ',enable_events=True,), sg.FolderBrowse('フォルダを選択', key='folder_from')],
    #2行目
    [sg.InputText('コピー先フォルダ',enable_events=True,), sg.FolderBrowse('フォルダを選択', key='folder_to')],
    #3行目
    [sg.Text('拡張子(ex:csv)', size=(15, 1)),sg.InputText('csv', size=(INPUT_BOX_SIZE, 1)),
     sg.InputText('xlsx', size=(INPUT_BOX_SIZE, 1)),sg.InputText('', size=(INPUT_BOX_SIZE, 1)),
     sg.InputText('', size=(INPUT_BOX_SIZE, 1)), sg.InputText('', size=(INPUT_BOX_SIZE, 1))],
    #4行目
    [sg.Submit(button_text='実行ボタン')]
]

# セクション 2 - ウィンドウの生成
window = sg.Window('ファイルコピー', layout)

# セクション 3 - イベントループ
while True:
    event, values = window.read()

    if event is None:
        print('exit')
        break

    if event == '実行ボタン':
        # フォルダのパスを抽出
        path_from = values['folder_from']
        path_to = values['folder_to']

        # 入力がある場合コピー対象とするように拡張子をリスト化
        ext_list =[]
        for i in range(MAX_NUM_EXT):
            if not len(values[INI_EXT_LINE+i].strip())==0:
                ext_list.append("." + values[INI_EXT_LINE+i].strip())

        # コピー関数実行
        copy_files(path_from, path_to, ext_list)

        # ポップアップ
        sg.popup("終了~")

# セクション 4 - ウィンドウの破棄と終了
window.close()
6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9