bat[001]サブフォルダ内のファイルを一箇所に集める

あるフォルダの配下にあるすべてのサブフォルダ内の特定の種類のファイルを一箇所に集めたい場合がある。

例えば、配下の複数のサブフォルダに散らばって保存されているすべてのPDFファイルを親フォルダに一同に集めたい場合、以下のコードをメモ帳にコピペして拡張子 .bat で保存し、それをダブルクリックして実行すると、このバッチファイルがあるフォルダに、配下のサブフォルダに保存されているPDFファイルをすべて集める(移動する)ことができる。

@echo off
for /r %%F in (*.pdf) do move /y %%F


たったこれだけのコードだが、バッチファイルにおける for文(繰り返し処理)の基本と言ってよい。

1行目の @echo off は、バッチファイルのコードをコマンドプロンプト上でいちいち表示させないようにする命令だ。この行を消して実行してみればどういう違いがあるかわかるだろう。
2行目がバッチファイルにおける for文で、基本的に for A in B do C という構造になっている。
B という集まりの中のそれぞれの要素(A)を順番に C しなさい、という意味だ。


/r というのはオプションと呼ばれるもので、この場合は for文の処理範囲を示しており、サブフォルダも対象にするという意味だ。
では、サブフォルダの親フォルダはどのフォルダだろうか? もちろん現在のフォルダ(カレントディレクトリ)である。
バッチファイルを実行する場合、通常カレントディレクトリはそのバッチファイルが置かれているフォルダだが、[管理者として実行]の場合は、

C:\Windows\system32

がカレントディレクトリになってしまうので注意が必要だ。カレントディレクトリを任意に特定したいときは cd コマンドを使う。
このように、バッチファイルでは常にカレントディレクトリに注意する必要がある。

なお、オプションは / + アルファベット1文字で表すので、その記述を見たらオプションを示していると思えばよい。


%%F は、for文の中でのみ有効な特殊な変数で、forで回す対象の各要素を示しており、%% + アルファベット1文字で記述するが、アルファベットの大文字と小文字は別物として扱われる。
in に続くカッコ()の中に for で回す対象を記述する。アスタリスク「*」はワイルドカードと言って、あらゆる文字列の代わりとすることができる。したがって、ファイル名が .pdf で終わるすべてのファイルを対象とする。
do に続けて、要素に対して処理する内容を記述する。このコードでは、対象の各要素(%%F)をカレントディレクトリに移動するように命じている。/y というのは moveコマンドのオプションで、同名のファイルがあったときに警告なく上書きするためのオプションである。
本プログラムと同様の処理は VBScript などでも記述することはできるが、何階層にもおよぶ配下のフォルダを走査するためには再帰処理で記述しなければならず、このバッチファイルのように到底1行で書き切ることは不可能だ。むろん、各要素に複雑な処理を施したい場合は再帰処理で書いたほうが楽なケースもあるが、本プログラムのように移動するだけとか、あるいはファイル名を抽出するだけといったような用途にはバッチファイルのコードのほうがはるかに簡単に書ける。

このようなツールが標準で装備されているので使わない手はないのである。



<注>
このコードをバッチファイルとしてではなく、コマンドプロンプトで直に打ち込んで実行する場合、変数 %%F は %F と、%ひとつで記述する。