不要なRAWをゴミ箱送りにするpythonスクリプトをChatGPTに書いてもらった

<!-- vi: se tw=1000 noet sw=2 ts=4 sts=2 et wrap nolbr : -->

不要なRAWファイルを削除して、ディスク容量を圧迫しないようにしようというお話です。

[前々回](https://qiita.com/azuwai2/items/4f796081fe0d90122dbe)の写真の一元管理、[前回](https://qiita.com/azuwai2/items/3a8ddf41f162bb4941e2)のミラーリングバックアップから、引き続いて写真整理ネタ。使うのは、再びpythonです。

　
そして、今回はコードを書く部分は流行りのChatGPTさんにお願いしてみました。
ChatGPT先生にpythonのコードを書いてもらうやり取りとコードを載せています。
※ChatGPTの発言は主にコードだけ抜粋しています。

# 本件に取り組んだ理由

ビューアで写真を見ているとき、RAWファイルは鬱陶しいので表示しないようにしています。・・・で、そのビューア上で不要なJPGファイルを削除していくのですが、当然RAWは残っています。

気付けばRAWの方も消しますし、むしろJPGは残しても「もう再現像はしないからこのJPGだけでいいや」という写真のRAWを消したりもするのですが、やはり漏れはあります。

ググるとバッチファイルで一発ドカンと、JPGの存在しないRAWを削除するノウハウなどは出てきたのですが、「単純に完全に同名のJPGファイルが居ない場合」の対処方法でした。

`*.JPG(実際は色々ある)`を`*.DEL`にコピーしておいて、`*.RAW(実際は色々ある)`を`*.DEL`にリネームさせると、JPGと被るものはリネームされずにRAWのまま残るので、あとは`*.DEL`を消す。・・・というやつです。

以下の理由で、ちょっとどうしようかなー、と思っていました。
- 写真整理フォルダ配下の、各サブフォルダの全部に対してそれを実施したい。
- 画像ファイル分のDELファイルが複製されるだけでもディスク容量を圧迫しそう。
- 画像ファイルの拡張子はJPGだけというわけではない。
- RAWファイルの拡張子も、一種類だけではない。

もう一つ不安だったのが、**ファイル名が完全に一致するJPGが存在しない場合には、RAWファイルは削除されてしまう**という点です。

もし、カメラで撮った後で「あー暗すぎたな」とか思って、カメラ内現像でRAW→JPGを行って、元のJPGを消した・・・という場合、ファイル名の関係性は泣き別れになります。

「そのRAWなら、JPGねーから消しときましたぜ旦那ァ」とか言われても後の祭りです。
せめて直接削除ではなく、ゴミ箱に入れるようにしたいです。

# 追加案件
「JPG消したから当然RAWも要らないや」は当たり前です。
せっかくやるからには、「JPGだけで、もうRAWは要らないや」という写真も見つけられるようにしたいです。

とは言え、JPGがあるのにRAWが要るのか要らないかまでは、流石に機械任せにできません。
（最近は、ピンぼけ写真かどうかまで、機械任せにできつつある世の中らしいですが。。）

ということで、フォルダ単位でRAWファイル残存率を調べて、「このフォルダなんにも考えずにRAW残ってるなー」というフォルダを、整理フォルダ内から見つけられるようにしたいのです。ディスクリソースの有効活用のために。

もしJPGに対して9割RAWが残っていたりしたら、要らないRAWがあるはずでしょう。
むしろそんなフォルダは、とりあえずJPG+RAWで撮った後、カメラからPCに取り込まれたまま、見返されてすらいない気配が濃厚です。


# ツールを作ってみる。
## 環境
・Windows 11
・Python 3.11.4
・Send2Trash 1.8.2


## まずはメインループ
[前々回](https://qiita.com/azuwai2/items/4f796081fe0d90122dbe)は、単純に全ファイルを対象に、どこに移動させるのか？、という話だったので、`glob.glob()`を使いました。（厳密には、同一フォルダ内の情報を参照したりしましたが。処理の単位としてはファイルでした。）

今回はファイル単位の処理がメインですが、RAW残存率確認のため、フォルダ単位での処理も必要になります。そこで、前回は使用しなかった`os.walk()`を使ってみようと思います。

とりあえず、こんな感じでしょうか。
```.py
    for dirname,subfolders,filenames in os.walk(target_dir):
        print(dirname)
        for filename in filenames:
            fname,exe=os.path.splitext(filename)         #ファイル名と拡張子
            print('\t',fname,exe)
```
このサンプルは、フォルダ名と、インデントして中身のファイル名と拡張子・・・をズラっと出すだけです。

あとは、RAWファイル名のキーで辞書でも作って、値にJPGファイル名を探して入れる感じにして、「JPGファイルが見つかってないね」、となったRAWを削除する。・・・とかすれば、よさそうです。

あとは、フォルダ内の、（RAWファイル数／JPGファイル数）で、RAWファイル存在比率をフォルダごとに出すと。

あー、これ完成したな。後はもうコード書くだけだわ、打つのめんどくさいな。。

## 「誰かー、あとはこの仕様で作っておいてくれ！」
・・・という感じなので、

> pythonで、os.wolk()を使って、指定したフォルダのすべてのサブフォルダに対して、RAWファイルに対応するJPGファイルが存在しないファイルを探し出して削除するコードを書いてください。ついでに、RAWファイル数÷JPGファイル数をフォルダごとに表示してください。

と、ChatGPTに適当な口語でお願いしてみました。

```.py
import os
import rawpy
import shutil

def delete_unmatched_raw_files(folder_path):
    for root, dirs, files in os.walk(folder_path):
        raw_files = [file for file in files if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3'))]
        jpg_files = [file for file in files if file.lower().endswith('.jpg')]

        if not jpg_files:
            # JPGファイルが存在しない場合、RAWファイルを削除
            for raw_file in raw_files:
                raw_file_path = os.path.join(root, raw_file)
                print(f"Deleting unmatched RAW file: {raw_file_path}")
                os.remove(raw_file_path)
                
            # RAWファイル数÷JPGファイル数を表示
            raw_count = len(raw_files)
            jpg_count = len(jpg_files) if jpg_files else 1  # ゼロ除算を避けるため
            ratio = raw_count / jpg_count
            print(f"Folder: {root}, RAW/JPG ratio: {ratio:.2f}\n")

# 使用例
folder_path = "path/to/your/folder"
delete_unmatched_raw_files(folder_path)
```

でました。
`import rawpy`がナゾですが、RAWファイルを扱ったりするのでとりあえずimportしてみたのでしょうか。
`root,dirs,files`うーん。シンプルでいい変数名ですね。今度パクりましょう。
拡張子を小文字にしてから見ているのも当たり前の事ですが、いいですね。指示してなくてもちゃんとやってくれるんですね。

リストに詰めてるっぽいのは分かる。まぁ、後は動かしてみながら見てみよう。

動かしてみていきなりファイルが抹消されてしまうのは怖いので、
「send2trashを使ってゴミ箱に入れるようにしてください。」とお願いしてみましょう。

> send2trashを使用してファイルをゴミ箱に送るように修正したコードは以下の通りです。send2trashは、ファイルを完全に削除せずに、ゴミ箱に移動することができるライブラリです。まず、send2trashをインストールします。
> 
> pip install send2trash
> 次に、以下が修正されたコードです。
> ・・・

と親切に教えてくれます。

あとは、「printで表示しているメッセージを日本語にしてください。」とか「画像ファイルの拡張子の種類に'.jpeg'を、RAWファイルの拡張子には'.dng'を追加してください。」とか、自分でやれよ的なこともフランクにお願いしてみましたが、イヤな顔一つせずに毎回即レスしてくれます。
※本当に、鍵カッコ内の言葉でそのまま打ち込んでいます。

こうなりました。
```.py
import os
import rawpy
from send2trash import send2trash

def delete_unmatched_raw_files(folder_path):
    for root, dirs, files in os.walk(folder_path):
        raw_files = [file for file in files if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3', '.dng'))]
        image_files = [file for file in files if file.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'))]

        if not image_files:
            # 画像ファイルが存在しない場合、RAWファイルをゴミ箱に移動
            for raw_file in raw_files:
                raw_file_path = os.path.join(root, raw_file)
                print(f"不一致のRAWファイルをゴミ箱に移動中: {raw_file_path}")
                send2trash(raw_file_path)
                
            # RAWファイル数÷画像ファイル数を表示
            raw_count = len(raw_files)
            image_count = len(image_files) if image_files else 1  # ゼロ除算を避けるため
            ratio = raw_count / image_count
            print(f"フォルダ: {root}、RAW/画像 比率: {ratio:.2f}\n")

# 使用例
folder_path = "path/to/your/folder"
delete_unmatched_raw_files(folder_path)
```
なんなら、サービス精神旺盛にjpeg以外の画像の拡張子まで足してくれています。
後は動けば言うことなしですが・・・。さっそく試してみましょう。

## テストデータ作成
テストに本物の写真である必要はないので、適当にフォルダを掘って、ダミーファイルを作ってみましょう。流石にこの程度は自分で準備します。

cr3は一つも削除されず、a,b両フォルダともRAWが100%残っている。という結果になるはずです。
```.bat
@echo off
cd %~dp0

mkdir a
cd a
copy nul 01.jpg
copy nul 02.jpg
copy nul 03.jpg
copy nul 04.jpg
copy nul 05.jpg
copy nul 06.jpg
copy nul 07.jpg
copy nul 08.jpg
copy nul 09.jpg
copy nul 10.jpg

copy nul 01.cr3
copy nul 02.cr3
copy nul 03.cr3
copy nul 04.cr3
copy nul 05.cr3
copy nul 06.cr3
copy nul 07.cr3
copy nul 08.cr3
copy nul 09.cr3
copy nul 10.cr3

cd ..
mkdir b
cd b
copy nul 01.jpg
copy nul 02.jpg
copy nul 03.jpg
copy nul 04.jpg
copy nul 05.jpg
copy nul 06.jpg
copy nul 07.jpg
copy nul 08.jpg
copy nul 09.jpg
copy nul 10.jpg

copy nul 01.cr3
copy nul 02.cr3
copy nul 03.cr3
copy nul 04.cr3
copy nul 05.cr3
copy nul 06.cr3
copy nul 07.cr3
copy nul 08.cr3
copy nul 09.cr3
copy nul 10.cr3
```

## 初回起動

動かしてみたところ、結果はこうでした。
```
フォルダ: Z:\テストデータ、RAW/画像 比率: 0.00
```
aもbもスルーです。
・・・os.walk()だったし、サブフォルダ見てないわけないよな。。


ちなみに、フォルダ上に存在しているファイルはこんな感じです。（上述したバッチファイルの通りなのですが、念のため確認）
```.cmd
Z:\>tree /f テストデータ
フォルダー パスの一覧:  ボリューム xxxxx
ボリューム シリアル番号は xxxx-xxxx です
Z:\テストデータ
│  a.bat
│
├─a
│      01.cr3
│      01.jpg
│      02.cr3
│      02.jpg
│      03.cr3
│      03.jpg
│      04.cr3
│      04.jpg
│      05.cr3
│      05.jpg
│      06.cr3
│      06.jpg
│      07.cr3
│      07.jpg
│      08.cr3
│      08.jpg
│      09.cr3
│      09.jpg
│      10.cr3
│      10.jpg
│
└─b
        01.cr3
        01.jpg
        02.cr3
        02.jpg
        03.cr3
        03.jpg
        04.cr3
        04.jpg
        05.cr3
        05.jpg
        06.cr3
        06.jpg
        07.cr3
        07.jpg
        08.cr3
        08.jpg
        09.cr3
        09.jpg
        10.cr3
        10.jpg
```

うむ、テストデータ直下の`a.bat`にしか反応していないっぽい。

　
よく見ると、「**対応する**画像ファイルが存在しない場合」ではなく、
単純に「**フォルダ内に**画像ファイルが存在しない場合」で判定しているように見えます。

　
　
　
　
**うわー！これに気がづかなかったのは恥ずかしい。。**

　
なーにが、
>拡張子を小文字にしてから見ているのも当たり前の事ですが、いいですね。指示してなくてもちゃんとやってくれるんですね。

・・・だ！

　
たしかに、「対応する」という指示だけで、「ファイル名部分の一致で対応する」というところまでは汲み取ってくれないのは、まぁ当たり前といえば当たり前でしょうか。
「対応するってどうしたらいいの？」って質問してこずに、シレッと答えてくるのがこの子の悪いところだよね。。

## 修正依頼

いや、お願いの仕方が悪かったんだよね。うむ。
イチから説明するのはめんどくさいので、簡潔に追加オーダーを投入！
「JPGファイルとRAWファイルの、ファイル名から拡張子を除いた部分が一致しているかどうかで対応付けを行ってください。」

>理解しました。ファイル名から拡張子を取り除いた部分が一致するかどうかで、JPGファイルとRAWファイルを対応付けるように修正します。以下が修正後のコードです。

はい有能。

・・・有能？
おいィ！JPGファイルまでゴミ箱に放り込んでるじゃねーか！
```.py
import os
import rawpy
from send2trash import send2trash

def delete_unmatched_raw_files(folder_path):
    for root, dirs, files in os.walk(folder_path):
        raw_files = [file for file in files if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3', '.dng'))]
        jpg_files = [file for file in files if file.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'))]

        # RAWファイルとJPGファイルを対応付け
        raw_dict = {os.path.splitext(raw_file)[0].lower(): raw_file for raw_file in raw_files}
        jpg_dict = {os.path.splitext(jpg_file)[0].lower(): jpg_file for jpg_file in jpg_files}

        # 一致しないRAWファイルをゴミ箱に移動
        for raw_name, raw_file in raw_dict.items():
            if raw_name not in jpg_dict:
                raw_file_path = os.path.join(root, raw_file)
                print(f"不一致のRAWファイルをゴミ箱に移動中: {raw_file_path}")
                send2trash(raw_file_path)

        # 一致しないJPGファイルをゴミ箱に移動
        for jpg_name, jpg_file in jpg_dict.items():
            if jpg_name not in raw_dict:
                jpg_file_path = os.path.join(root, jpg_file)
                print(f"不一致のJPGファイルをゴミ箱に移動中: {jpg_file_path}")
                send2trash(jpg_file_path)

        # RAWファイル数÷JPGファイル数を表示
        raw_count = len(raw_files)
        jpg_count = len(jpg_files)
        ratio = raw_count / jpg_count if jpg_count else 0  # ゼロ除算を避けるため
        print(f"フォルダ: {root}、RAW/JPG 比率: {ratio:.2f}\n")

# 使用例
folder_path = "path/to/your/folder"
delete_unmatched_raw_files(folder_path)
```

「削除したいのはRAWだけで、JPGの削除はしないでください。」
```.py
import os
import rawpy
from send2trash import send2trash

def delete_unmatched_raw_files(folder_path):
    for root, dirs, files in os.walk(folder_path):
        raw_files = [file for file in files if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3', '.dng'))]
        jpg_files = [file for file in files if file.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'))]

        # RAWファイルとJPGファイルを対応付け
        raw_dict = {os.path.splitext(raw_file)[0].lower(): raw_file for raw_file in raw_files}
        jpg_dict = {os.path.splitext(jpg_file)[0].lower(): jpg_file for jpg_file in jpg_files}

        # 一致しないRAWファイルをゴミ箱に移動
        for raw_name, raw_file in raw_dict.items():
            if raw_name not in jpg_dict:
                raw_file_path = os.path.join(root, raw_file)
                print(f"不一致のRAWファイルをゴミ箱に移動中: {raw_file_path}")
                send2trash(raw_file_path)

        # RAWファイル数÷JPGファイル数を表示
        raw_count = len(raw_files)
        jpg_count = len(jpg_files)
        ratio = raw_count / jpg_count if jpg_count else 0  # ゼロ除算を避けるため
        print(f"フォルダ: {root}、RAW/JPG 比率: {ratio:.2f}\n")

# 使用例
folder_path = "path/to/your/folder"
delete_unmatched_raw_files(folder_path)
```

よし、試してみよう。・・・の前に一応読んでみようか。

確か自分が冒頭に思い描いたことは、こんな感じ。

>あとは、RAWファイル名のキーで辞書でも作って、値にJPGファイル名を探して入れる感じにして、「JPGファイルが見つかってないね」、となったRAWを削除する。・・・とかすれば、よさそうです。


ChatGPTさんは、一連のやり取りから、どのように実装してくれたかというと・・・

RAWとJPGのそれぞれの拡張子を除いた部分をキーとした辞書を作って、ファイル名を値として保持。辞書が2個あるのは、JPGファイル名を探す用ですね。うむうむ。

拡張子を除いた部分を小文字化している意味はイマイチ分かりませんね。。
大文字小文字を別ファイルと認識するファイルシステムだったら、困っちゃいます。
まぁ、Windowsなのでいいんですが。

で、RAWの辞書を回しながら、JPGの辞書にキーが一致するものがない場合に、ごみ箱へポイ。いいですねー。

あー、消し終わった後のRAWの数をもとに、残存率を出してほしいな。惜しい！

 　
というわけで「削除し終わった後に残ったRAWファイルの個数をもとに、RAWファイル数÷JPGファイル数を計算してほしいな。比率は%表示にしてください。」
とちょっとフレンドリーにお願いしてみます。
　
愛着がわいてくると口調が柔らかくなるものですね。

```.py
import os
from send2trash import send2trash

def delete_unmatched_raw_files(folder_path):
    for root, dirs, files in os.walk(folder_path):
        raw_files = [file for file in files if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3', '.dng'))]
        jpg_files = [file for file in files if file.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'))]

        # RAWファイルとJPGファイルを対応付け
        raw_dict = {os.path.splitext(raw_file)[0].lower(): raw_file for raw_file in raw_files}
        jpg_dict = {os.path.splitext(jpg_file)[0].lower(): jpg_file for jpg_file in jpg_files}

        # 一致しないRAWファイルをゴミ箱に移動
        for raw_name, raw_file in raw_dict.items():
            if raw_name not in jpg_dict:
                raw_file_path = os.path.join(root, raw_file)
                print(f"不一致のRAWファイルをゴミ箱に移動中: {raw_file_path}")
                send2trash(raw_file_path)

        # 残ったRAWファイルの個数
        remaining_raw_files = [file for file in os.listdir(root) if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3', '.dng'))]

        # RAWファイル数÷JPGファイル数を%表示で表示
        raw_count = len(remaining_raw_files)
        jpg_count = len(jpg_files)
        ratio = (raw_count / jpg_count) * 100 if jpg_count else 0  # ゼロ除算を避けるため
        print(f"フォルダ: {root}、残ったRAWファイル数: {raw_count}、RAW/JPG 比率: {ratio:.2f}%\n")

# 使用例
folder_path = "path/to/your/folder"
delete_unmatched_raw_files(folder_path)
```
ちゃんと対応してくれました。

`残ったRAWファイル数:`というメッセージが可愛い感じですね。
細かい仕事だと感心するが、そこまで変えなくてもいい。
個数の表示自体もいらないから。残った個数で比率を出してほしかっただけだから。

まぁ、その程度は後で自分で修正しましょう。
どうお願いしたら伝わるか考えるほうがめんどくさいので。。

## 動作確認
では、さっそく動かしてみます。

テストデータフォルダから、
- aフォルダの`1.jpg`と`2.jpg`
- bフォルダの`1.cr3`と`2.cr3`
を削除してから実行した結果がこちらです。

```
フォルダ: Z:\テストデータ、残ったRAWファイル数: 0、RAW/JPG 比率: 0.00%
不一致のRAWファイルをゴミ箱に移動中: Z:\テストデータ\a\01.cr3
不一致のRAWファイルをゴミ箱に移動中: Z:\テストデータ\a\02.cr3
フォルダ: Z:\テストデータ\a、残ったRAWファイル数: 8、RAW/JPG 比率: 100.00%
フォルダ: Z:\テストデータ\b、残ったRAWファイル数: 8、RAW/JPG 比率: 80.00%
```

**ありがとう！ChatGPT！君は素晴らしい。**

# 完成版
## raw2trash.py
表示を見直しました。
削除するツールだってことを分かって動かすので、「ごみ箱に移動中：」を毎回出すとこは要らないかなと。ファイル名だけ出ればいいです。

「残ったRAWファイル数」もいらないですし、小数点2位まで出したいようなものでもないです。
比率の表示は整数にして、表示桁位置を合わせました。
毎回「比率」とかいう文言もいらないので（日本語にしてとかこっちからお願いしたくせに）消しました。

あとは、コマンドラインから引数を渡してみたり、RAW/JPG比率の閾値を指定できるようにしたりしました。毎回全フォルダを表示されても困るので。

```.py
import os,sys
from send2trash import send2trash

def delete_unmatched_raw_files(folder_path):
    for root, dirs, files in os.walk(folder_path):
        raw_files = [file for file in files if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3', '.dng'))]
        jpg_files = [file for file in files if file.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'))]

        # RAWファイルとJPGファイルを対応付け
        raw_dict = {os.path.splitext(raw_file)[0].lower(): raw_file for raw_file in raw_files}
        jpg_dict = {os.path.splitext(jpg_file)[0].lower(): jpg_file for jpg_file in jpg_files}

        # 一致しないRAWファイルをゴミ箱に移動
        for raw_name, raw_file in raw_dict.items():
            if raw_name not in jpg_dict:
                raw_file_path = os.path.join(root, raw_file)
                print(os.path.join(root,raw_file_path))
                send2trash(raw_file_path)

        # 残ったRAWファイルの個数
        remaining_raw_files = [file for file in os.listdir(root) if file.lower().endswith(('.cr2', '.nef', '.arw', '.cr3', '.dng'))]

        # RAWファイル数÷JPGファイル数を%表示で表示
        raw_count = len(remaining_raw_files)
        jpg_count = len(jpg_files)
        ratio = int((raw_count / jpg_count) * 100) if jpg_count else 0  # ゼロ除算を避けるため
        if ratio_limit <= ratio :
            print(f"RAW/JPG : {ratio: >3}%, {root}")

################################################################################
msg_err1='引数が1つ必要です。RAWファイル削除対象フォルダを指定してください。'
msg_err2='第2引数を指定する場合は、数値でRAW比率の閾値を指定してください。指定しない場合は100（すべて表示）です。'

#1 python a.py              :error
#2 python a.py 'xx'         :100%
#3 python a.py 'xx' 90      :90%

if not 2 <= len(sys.argv) <= 3:
    print(f'{msg_err1}\n{msg_err2}')
    sys.exit()

folder_path = sys.argv[1]
if not os.path.isdir(folder_path):
    print(folder_path,'はフォルダではありません。フォルダを指定してください。')
    sys.exit()

if len(sys.argv) == 3:
    if sys.argv[2].isdecimal():
        ratio_limit=int(sys.argv[2])
    else:
        print(msg_err2)
else:
    ratio_limit=100

#print('対象フォルダ :',folder_path)
#print('RAW/JPG閾値  :',ratio_limit,'%\n')

delete_unmatched_raw_files(folder_path)
```

## raw2trash.bat
パスをドラッグ＆ドロップとかしたいのですが、EXE化とかめんどくさそうだったので、
バッチファイルで包んで、ドラック&ドロップされたパスを引数に渡すようにしたりしました。

```.bat
@echo off
set script=raw2trash

python %~dp0%script%.py %1 90 > %script%.log
type %script%.log

@echo\
pause

```

本当は、tee的な感じに、画面に出しつつ、ログファイルにも書きたかったのですが、とりあえずリダイレクトでログ出力して、処理が終わった後にログを表示。
windowsってteeってないんですね。

~~・・・思いついた！~~
~~次の記事では、ChatGPTさんにtee的なpyを書いてもらうようにお願いしてみようかと思います。~~
→やめました。一瞬で回答をもらえてしまってつまらなかったですし、実質使いどころもありませんでしたし、kaoriyaのgvimのなかにtee.exe入ってたりしましたし…。

## 最終動作確認
テストデータフォルダを`raw2trash.bat`にドラッグすると、お馴染みの黒い窓に、こんな感じに表示されます。
```
Z:\テストデータ\a\01.cr3
RAW/JPG : 100%, Z:\テストデータ\a
RAW/JPG :  90%, Z:\テストデータ\b

続行するには何かキーを押してください . . .
```

ちゃんとRAWがゴミ箱に格納されていることも確認しました。
※Z:はネットワークドライブをマウントしたものだったので、最初はゴミ箱に入っておらず首をかしげていたのですが、D:等にテストデータを作って試しました。

写真原本に対しても実施してみて、ちゃんと不要なRAWがゴミ箱送りされることを確認しました。
むしろ、RAW/JPGが100%のフォルダとかがボコボコ出てきて、しかも連写とかしてて、不要なファイルを消していったら1フォルダ当たり数百メガずつ消せそうです。スバラシイ。

処理自体も、数秒で終わったので、teeとかする必要ないかも。
なんなら、削除確認と削除実施の2段構えで処理してもいいくらいに軽かったです。


# 最後に
ChatGPTとのやり取りを含めて、なかなかに楽しい時間でした。
もっといろんなコードを書いてもらいたくなってきます。
　
ただ、意図通りになっていない事があるので、出てきたコードはちゃんと読んで確認しないと要注意だと感じました。とはいえこの程度の内容だとピンポイントに指摘するだけで、今までのやり取りを踏まえて修正してくれるみたいです。スゴイですね。

　
何といっても、変数名を考えなくていいのが一番楽かも。