FOR コマンドに、/F オプションを指定すると、指定したテキストファイル内の各行をループで処理することができます。
ここでは、入力データとして、下記のようなテキストファイルを使用します。
A1 A2 A3 A4 A5
B1 B2 B3 B4 B5
C1 C2 C3 C4 C5
次のバッチファイルは、data.txt の内容を一行ずつループで取得して表示しています。
@echo off
FOR /F %%A IN (data.txt) DO echo %%A
A1
B1
C1
あれ???各行が 1 単語ずつしか表示されませんね。
これは、FOR /F コマンドが、デフォルトでは スペースやタブ をデリミタとして、各フィールドを区切って変数に格納するからです。
一行全体を %%A に取得するには、下記のようにデリミタ文字を delims= オプションで無効にしてしまうか、tokens=* としてすべてのフィールドをまとめて取得します。
FOR /F "delims=" %%A IN (data.txt) DO echo %%A
FOR /F "tokens=*" %%A IN (data.txt) DO echo %%A
A1 A2 A3 A4 A5
B1 B2 B3 B4 B5
C1 C2 C3 C4 C5
デリミタで区切られた各フィールドの値を %%A、%%B、%%C、%%D、%%E というそれぞれの変数に取得したい場合は、下記のように tokens オプションを指定します。
FOR /F "tokens=1-5" %%A IN (data.txt) DO echo %%A %%B %%C %%D %%E
A1 A2 A3 A4 A5
B1 B2 B3 B4 B5
C1 C2 C3 C4 C5
上記では、1 番目から 5 番目のフィールドを取得するように tokens=1-5 と指定していますが、tokens=2,3 のように、任意の位置のフィールドのみを抜き出すこともできます。
FOR /F "tokens=2,3" %%A IN (data.txt) DO echo %%A %%B
A2 A3
B2 B3
C2 C3
なお、tokens オプションで指定したフィールド番号の順序は、実行結果に影響しません。
例えば、tokens=3,2 と番号を逆順で指定しても、%%A には 2 番目のフィールドの値(A2 など)が格納されます。
FOR /F コマンドの集合に、ダブルクォーテーション " で囲まれた文字列を渡すと、その文字列そのものがパースされます(ファイル名とはみなされない)。
FOR /F "tokens=1,3" %%A IN ("aaa bbb ccc") DO echo %%A %%B
aaa ccc
この仕様のおかげで、スペースを含んだファイル名を指定することが難しくなっています。
例えば、read me.txt というファイル名を指定したとします。
FOR /F "tokens=1" %%A IN ("read me.txt") DO echo %%A
上記の結果は、read と表示されて終わりです。
これは、read me.txt という文字列がダブルクォーテーション " で囲まれているため、それがテキストデータそのものだと判断されているからです。
この振る舞いを抑制し、ファイル名だと判断させるには、下記のように usebackq オプションを指定します。
FOR /F "tokens=1 usebackq" %%A IN ("read me.txt") DO echo %%A
FOR /F コマンドでは、テキストファイルの中身を処理するだけではなく、任意のコマンドの出力結果を扱うことができます。
下記のバッチファイルは、環境変数の一覧を表示する set コマンドの出力を FOR /F ループで一行ずつ処理しています。
デリミタを = に設定し、1 番目のフィールドを指定することによって、環境変数名だけを抽出しています。
@echo off
FOR /F "delims== tokens=1" %%A IN ('set') DO echo %%A
C:\> vars
...
NUMBER_OF_PROCESSORS
OS
Path
PATHEXT
PROCESSOR_ARCHITECTURE
PROCESSOR_IDENTIFIER
PROCESSOR_LEVEL
...