やあ子供たち元気でやっているか。今日はWindowsのバッチファイルを書いて遊ぶお話だよ。
今回はフォルダ階層をその深さ方向へ隈なく辿る再帰処理バッチファイルを書いてみるよ。その中で、バッチファイルの中におけるサブルーチンの実装のやり方や、tree文の便利な使い方についても見ていくよ。では早速いってみよう。
バッチファイルの起動方法として、
- ダブルクリックする
- 引数となるファイルやフォルダをドラッグ&ドロップする
- 他のバッチファイルから呼び出す
といういくつかのやり方があるが今回は2番目の方法を想定しよう。何か処理対象のファイルなりフォルダなりがある場合は、2番目の使い方を想定した処理を書くのが、デバッグしやすいし、また完成した際のサブルーチン化も容易で、再利用しやすいという利点もあり、一番いいからだ。
なので今回のターゲットで言えばつまり、「ドラッグ&ドロップされた任意のフォルダの中身をそのフォルダ階層の深さ方向に隈なく探索&移動して、帰ってくるだけのバッチファイル」を書くことにしよう。
それは以下のプログラムのようになった。
@echo off rem *** 前半部分 ***(サブルーチン呼び出し)) call :func %1 pause goto :eof rem *** 後半部分 ***(サブルーチン定義) :func set arg=%1 pushd %arg% for /D %%i in (*.*) do ( call :func "%%i" ) popd exit /b
いかがだろうか。前半部分がプログラム本体で後半部分がサブルーチン定義だよ。前半部分の%1はドラッグ&ドロップされてきたファイルのフルパス情報を保持しているのに対し、サブルーチン定義の中の%1ではこれを第一引数としての意味で使っており、つまり同じバッチファイルの中で%1と書いてあっても文脈によってその意味は異なるという点に注意してほしい。
そして今回は再帰呼び出しをするので、サブルーチン内部で自分自身を呼んでいるね。何をやっているかというと、まず指定フォルダの中に移動する。そしてその中にあるフォルダのそれぞれについて、それを引数として自分自身を呼び出し、全て終わったらもとの場所に戻る、というだけの処理だよ。
サブルーチンとはいっても単にラベル定義で始まる処理を書いて、最後にexit /bを記述しただけのものだ。そして呼ぶときはcall文を使うというだけのことだ。
自分自身を呼ぶところで、どうして%%iの両側にダブルクォーテーションがついているのかというとそれはスペースを含むフォルダ名の場合への対処なんだね。バッチファイルにファイルやフォルダをドロップした場合、ダブルクォーテーションつきのフルパス情報が第一引数として入ってくるのだけど、for /D 文を使ってフォルダを巡回した際は、個々のフォルダ名にはダブルクォーテーションはついていないんだ。なのでこの点は覚えておくといいかも知れない。
さてドロップされた任意のフォルダの中を巡るだけでは何も起きないし面白くないので、例えば以下のように処理を追加してみるよ。
@echo off rem *** 前半部分 ***(サブルーチン呼び出し)) call :func %1 pause goto :eof rem *** 後半部分 ***(サブルーチン定義) :func set arg=%1 pushd %arg% for /D %%i in (*.*) do ( call :func "%%i" ) mkdir a// ★ mkdir b// ★ popd exit /b
★のコメントのある行が今回追加したところだよ。(実際には// ★はあると動かないので消してくれ)こうすると、巡った全てのフォルダの中で、★の処理が実行される、つまり、aとbというフォルダを作成して帰ってくるという処理内容だよ。
空のフォルダを一つ用意して、これを1回実行(上述のBATファイルにドラッグ&ドロップ)しただけの実行結果、ならびに2回、3回とこれを実行した際の実行結果を、tree文で打ち出してみたものを以下に示そう。
いかがだろうか。実行するたびにフォルダの中の階層が深くなり、aとbというフォルダが確実に作成されている様がおわかりかと思う。
フォルダを作るだけでは面白くないので、その中に3種類のイメージファイルを置く処理にしてみよう。以下のようなバッチファイルになったよ。
@echo off rem *** 前半部分 ***(サブルーチン呼び出し)) call :func %1 pause goto :eof rem *** 後半部分 ***(サブルーチン定義) :func set arg=%1 pushd %arg% for /D %%i in (*.*) do ( call :func "%%i" ) mkdir a mkdir b copy %userprofile%\desktop\image.bmp a //★ copy %userprofile%\desktop\image.png a //★ copy %userprofile%\desktop\image.gif a //★ copy %userprofile%\desktop\image.bmp b //★ copy %userprofile%\desktop\image.png b //★ copy %userprofile%\desktop\image.gif b //★ popd exit /b
(例によって★のコメントのある行が追加分だよ。//★の部分は残ってると動かないので実際には消してくれ)
そして2階層目まで実行したときのtree文の結果が以下だ。
いかがだろうか。フォルダをその深さ方向に再帰的に辿る処理の活用事例を紹介したよ。もっと実用性のある使い道はいくらでもあるのでちょっとみんなもいろいろ試してみてくれないか。
最後にtree文を便利につかうための方法として、以下のようなバッチファイルを作っておいて、その上に任意のフォルダをドラッグ&ドロップすれば、そのフォルダの中のフォルダ・ファイル階層が一目瞭然となり便利なので紹介しておくぞ。
@echo off
pushd %1
tree /f
popd
pause
それでは今日はこれまでだ。
チャオ!