ぱいそん 正規表現 の 改造 | 60歳を迎えて、思うこと。

60歳を迎えて、思うこと。

いつの間にか、「60」という年月が経ちました。
残り少ないか多いか?わかりませんが。
じじぃ~の「ひとりごと」を細々と続けられれば。。。

ぱいそん 正規表現 の 改造

わんわん
もふもふ

正規表現を(ちょっとだけ)!
使用して

ファイルの 振り分け

ちょっと 使いやすく
なるように


改造してもらった!

# ==== 【Gemini】様
# はい、もちろんです!設定エリアで**「対象の拡張子」**と**「検索モード(前方一致か全文検索か)」**をサクッと切り替えられるように改造しましょう。
# これなら、今後 `.jpg` や `.png` に変えたいときや、検索の厳しさを変えたいときも、下のコードをいじらずに済みます。
# ### 改造のポイント
# 1.  **`EXT_LIST`:** 拡張子をリストで指定できるようにしました(複数の場合も対応可)。
# 2.  **`MATCH_MODE`:** `"search"`(どこでも一致)か `"match"`(前方一致)を文字で選べるようにしました。
# 3.  **判定ロジックの共通化:** `getattr` という機能を使って、設定したモードに応じて動きを自動で切り替えます。

### 修正後のスクリプト


import os
import re
import shutil
from pathlib import Path

# --- 設定エリア ---
TARGET_DIR = r"E:\__WORK"
BASE_DEST = r"E:\__WORK-MOVE-BMP-正規表現"

# ★ 対象の拡張子(複数指定も可能。例: ['.bmp', '.jpg'])
TARGET_EXTS = ['.bmp']

# ★ 検索モードの設定
# "search" : 全文チェック(どこかに含まれればOK)
# "match"  : 前方一致(先頭から一致する必要あり)
MATCH_MODE = "search" 

# ★ ルール設定
RULES = [
    (r'法剣', "法剣"),
    (r'ライトグラム', "ライトグラム"),
    (r'プロファイル', "プロファイル"),
    (r'^Bless', "BLESS"),
    (r'NE555', "NE555"),
    (r'RF4', "RF4"),
    (r'E2C', "E-2C"),
    (r'太陽を盗んだ男', "太陽を盗んだ男"),
    (r'SSD', "SSD"),
    (r'ブレッド', "ブレッドボード"),
    (r'^[a][0-9]{2}$', "千里系"),
]

# --- 処理部 ---

def get_unique_path(path):
    if not os.path.exists(path):
        return path
    p = Path(path)
    counter = 1
    while True:
        new_path = p.with_stem(f"{p.stem}_{counter}")
        if not new_path.exists():
            return str(new_path)
        counter += 1

def main():
    # 正規表現を事前にコンパイル
    compiled_rules = [(re.compile(p), name) for p, name in RULES]
    
    # 拡張子を小文字のセットに変換(判定スピード向上のため)
    valid_exts = tuple(ext.lower() for ext in TARGET_EXTS)

    for root, _, files in os.walk(TARGET_DIR):
        for filename in files:
            # ★ 設定した拡張子以外はスキップ
            if not filename.lower().endswith(valid_exts):
                continue

            src_path = os.path.join(root, filename)
            name_only = os.path.splitext(filename)[0]
            moved = False

            # ★ ルール判定ループ
            for pattern, subfolder in compiled_rules:
                
                # 設定されたモード(search か match)を動的に取得して実行
                # getattr(pattern, "search") は pattern.search と同じ意味になります
                match_func = getattr(pattern, MATCH_MODE)
                
                if match_func(name_only):
                    dest_dir = os.path.join(BASE_DEST, subfolder)
                    os.makedirs(dest_dir, exist_ok=True)

                    dest_path = os.path.join(dest_dir, filename)
                    final_dest = get_unique_path(dest_path)

                    print(f"[{MATCH_MODE.upper()} MOVE] {filename} -> {final_dest}")
                    shutil.move(src_path, final_dest)

                    moved = True
                    break

            if not moved:
                print(f"[SKIP] {filename}")

if __name__ == "__main__":
    main()


### 使い方の解説
# *   **拡張子を変えたい時**
#     `TARGET_EXTS = ['.jpg', '.png']` のように書き換えれば、画像全般を対象にすることもできます。
# *   **マッチ方法を変えたい時**
#     `MATCH_MODE = "match"` に書き換えると、今までコメントアウトで切り替えていた「前方一致」に切り替わります。
# *   **ちょっとしたコツ**
#     設定エリアの `TARGET_EXTS` は、`.bmp` ではなく `bmp`(ドットなし)で書いちゃっても動くように `endswith` を使っていますが、基本はドットありで書くのが安全です。
# これで、スクリプトの心臓部を触らずに「設定」だけでお好みの挙動に変更できるようになりました!
# ==============================

他力本願な日々

お年頃♪

じじぃ~