たまにWindows用のバッチファイルを書くのですが、設定ファイルにファイルリストを書いて、それを1行ずつ読み込みながら何らかのコマンドを実行するforループの作り方を毎回探して苦労するので、自分用にまとめます。
仕様
- 設定用ファイルにデータのリストを書きます。
- そのリストを1行ずつ読み込みながら何らかのコマンドを実行します
- 設定用ファイルにある # から始まる行はコメント行とみなして飛ばします。
バッチファイル
mybatch.config
file01.txt
file02.txt
file03.txt
下記のバッチファイル中にある echo %%I
の部分を任意のコマンドに置き換えればいろいろできます。
mybatch.bat
@echo off
set datalist=mybatch.config
setlocal EnableDelayedExpansion
for /F %%I in (%datalist%) do (
set itemp=%%I
if not "!itemp:~0,1!"=="#" (
echo %%I
)
)
pause
実行すると以下のように出力されます。
結果
file01.txt
file02.txt
file03.txt
主な解説(覚書)
-
for /F %%I in (%datalist%) do
でdatalistに指定したファイルの中身をforeachできる。ファイルではなくリテラル指定の場合、for %%I in (file01.txt, file02.txt, file03.txt) do
のようにも書ける。 - 環境変数
%XXXX%
からsubstringするには、%XXXX:~m,n%
と書く。m番目(0開始)からn文字分抜き出す。mだけだとラストまで抜き出す。 - ループ用変数名はアルファベット1文字で
%%I
のように使う。アルファベット1文字は慣習ではなく仕様。 - ループ用変数をsubstringできない。なので一旦環境変数に再設定してからsubstringする。しかし、環境変数は実行時に1回しか評価されないので、そのままだと変数に何も設定されていない。よって遅延評価を有効にする(
setlocal EnabledDelayedExpansion
)。遅延評価される変数は%XXXX%
ではなく!XXXX!
で参照する。
大変参考になる記事
おまけ:日時をファイル名やフォルダ名に付与したい時の文字列生成
- 日付は、単純に
"/"
を空文字に置き換えて取得する。 - 時刻は、単純に
%time%
で取得すると、" 9:06:31.33"
のように、先頭に空白が入ってしまう為、一旦空白を0に置換し、その後、":"
を空文字に置換、最後に先頭6文字を抽出している。 - 最後に、それらの文字列を結合してフォルダ名を作り、なければフォルダを作成する。
SET yyyyMMdd=%date:/=%
SET hhmmss=%time: =0%
SET hhmmss=%hhmmss::=%
SET hhmmss=%hhmmss:~0,6%
SET backupfolder=backup%yyyyMMdd%_%hhmmss%
if not exist %backupfolder% mkdir %backupfolder%