Programming Field

For - DOS/コマンドプロンプト コマンド一覧

現在のディレクトリにあるファイルを列挙し、それらに対して任意のコマンドを実行します。いわゆる「for文」にあたります。

[Windows NT系] [拡張構文] オプションを指定してテキストの解析を行うこともできます。

構文

for %variable in (<pattern>) do <command-line>
for /D %variable in (<pattern>) do <command-line>
for /R [[<drive-letter>:]<path>] %variable in (<pattern>) do <command-line>
for /L %variable in (<start>,<step>,<end>) do <command-line>
for /F ["<options>"] %variable in (<pattern>) do <command-line>

バッチファイル内でForを使用する場合、「%%variable」のように「%」を2つ並べる必要があります。これは、1つだけだと環境変数の%と見なされて、その内容(または空白)に置き換えられてしまうからです。

※ Forに限らず、バッチファイル内でコマンドまたはプログラムに「%」文字そのものを渡したい場合は「%%」と記述します。「%」のページもご覧ください。

オプション一覧

%variable
変数名を定義します。「variable」には1文字の英数字を指定します。この変数は、下記の <command-line> で用いることができ、使用すると列挙中のファイル名に置き換えられます。なお、大文字・小文字が区別されます。
<pattern>
検索するファイル名を指定します。通常は複数のファイルを列挙するため、ワイルドカードを使用します。
また、複数のパターンをスペース区切りで指定することが可能です。(例: 「(*.txt *.log)」)
[Windows NT系] [拡張構文] /F オプションにおいては <pattern> の指定方法が一部変化します。詳しくは解説をご覧ください。
<command-line>
実行するコマンドを指定します。そのコマンドに対する引数も後ろに並べることが出来ます。このコマンドは、プロンプトに入力されるものと同じで、Echo なども使用できます。
%variable を含めることで、列挙中のファイルを引数に指定することが出来ます。
[Windows NT系] 「@」を先頭に用いると、コマンドを表示しないようにすることも可能です。また、「( )」を用いることで複数行のコマンドを一つのコマンドと見なして指定することもできます。「( )」を用いる場合は環境変数の展開のタイミングにご注意ください(詳しくは「( )」およびSetlocal「!」をご覧ください)。
/D
[Windows NT系] [拡張構文] ファイルではなくディレクトリを列挙するように変更します。
/R [[<drive-letter>:]<path>]
[Windows NT系] [拡張構文] 「[<drive-letter>:]<path>」で指定されたパスと、その中のサブディレクトリ内にあるファイルすべてを検索し、<pattern> に一致するファイルに対してコマンドを実行します(「[<drive-letter>:]<path>」を省略すると現在のディレクトリが使用されます)。<pattern> に「.」と指定するとディレクトリとサブディレクトリのみ(厳密にはその中の「.」ディレクトリ)が列挙されます。
/L ... (<start>,<step>,<end>)
[Windows NT系] [拡張構文] <start><end>の間の数値を列挙します(%variableには列挙した数値が入ります。一般的なプログラミング言語に存在するfor文に似ています)。列挙する数値は<start>で始まり<step>ずつ増やされ、<end>を超えたら終了します。<step>がマイナスの場合は、列挙する数値は<start>で始まり「-<step>」ずつ減らされ、<end>未満になったら終了します。いずれも最初から<start><end>(または <start><end>)になっている場合は列挙されません。
/F ["<options>"]
[Windows NT系] [拡張構文] <pattern> のデータを1行ずつ読み取って解析し、それらに対して <command-line> を実行します。%variableには解析した文字列が入ります。解析方法は「"<options>"」で指定します(解説参照)。
<pattern> にはファイル名(スペースやセミコロンで区切ることで複数指定可能です)、文字列(" "で囲みます)、コマンドライン(コマンドラインを' 'で囲みます)が指定可能で、それぞれファイルの中身、文字列そのもの、コマンドライン実行時の(標準出力への)出力結果を入力データとします。ただし、<options> に「usebackq」を含む場合は、文字列は「' '」で、コマンドラインは「` `」で囲む形式に変わります(これによりファイル名に「" "」を使用することができます)。
<pattern> にコマンドラインを指定する場合で、パイプやリダイレクションを使用する場合は、それらの文字の直前に「^」を用いることで使用可能ですが、複数のコマンドを「( )」を用いて記述(ネスト)すると正しく解釈されない場合がありますので、使用する際はご注意ください。

解説

Forについて

For使用例

Forコマンドはファイルを列挙してコマンドを実行します。例えば、あるディレクトリに対して「*.*」というパターンでForを実行することで、そのディレクトリ内にあるすべてのファイルに対して同じコマンドを実行することができます。ただし、実行するコマンドが対象のディレクトリにファイルを新たに作成すると、そのファイルも列挙されてしまいます。

構文中の「in」と「do」は、必ず記述する必要があります(記述しないと構文エラーとなります)。

このコマンドではディレクトリは列挙しません(「/D」を指定した場合を除く)。また、隠しファイルやシステムファイルの属性があるファイルも列挙対象になりません。

[Windows NT系] [拡張構文] 隠しファイルやシステムファイルも含めてForを実行したい場合は、DirコマンドとForの「/F」スイッチを組み合わせて実行する方法があります(サンプル8を参照)。

[Windows NT系] [拡張構文] 拡張構文が有効になっている場合(既定で有効になっています)、Forによって作成される変数の展開時に、バッチファイルの引数として使われる「%1」や「%2」と同様の「~」を使った拡張を使うことができます。具体的な書式は「%」をご覧ください。

拡張構文を使ったテキスト解析

[Windows NT系] [拡張構文] 「/F」オプションによりテキストデータの解析を行うことができます。この際「"<options>"」で指定できる解析オプションは以下の通りです。

eol=c 行末文字を1文字で指定します。cで指定された文字とそれ以降は解析の対象外になります。指定しない場合は改行文字の直前まで読み取られます。
skip=n 最初のn行を解析から外します。
delims=delimiters 区切り文字を指定します。delimitersには区切り文字として使う文字を指定します(複数指定可能ですが、1文字単位で使用されます)。delimitersにはスペースを含むことができますが、スペースを指定する場合スペースを必ず最後の文字にする必要があり、かつ「delims」オプションがすべてのオプションの中で最後に来る必要があります。なお、このオプションを省略した場合は区切り文字としてスペースとタブが使用されます。また、delimiters」が空の文字列の場合はデータを区切る処理が行われず、1行のデータがすべて %variable に入ります。
tokens=token[,token...] 解析結果のデータのうちどれを %variable に設定するかを指定します。このオプションを指定すると、%variableが「%1」の場合は「%2」「%3」、「%i」の場合は「%j」「%k」のように、%variable の他に変数が追加で用意されます。tokenには数値、範囲付き数値、「*」のどれかを指定します。数値は区切られたデータのn番目(1以上)、範囲付き数値は「m-n」のようにハイフンでつなげてm番目からn番目までのデータを %variable およびそれ以降の変数に与えるようにします。「*」を指定すると、tokenで指定されなかった分の残りのデータすべてを区切らずに変数に設定します。
usebackq <pattern> に指定するデータを「ファイル名」「"文字列"」「'コマンドライン'」から、「"ファイル名"」「'文字列'」「`コマンドライン`」の形式に変更します(この場合ファイル名は" "で囲まなくても構いません)。スペースや「( )」文字などがファイル名に含まれる場合は、このオプションを使用してファイル名を「" "」で囲む必要があります。

具体的な使い方はサンプル(サンプル5以降)をご覧ください。

delimitersを記述しない空の「delims=」指定と、「delims」指定そのものを省略した構文とでは、区切り文字に関する意味が異なります。区切り文字で分割せずに行全体を変数に与えたい場合は、明示的に「delims=」と指定を入れる必要があります(さらにスペースが区切り文字として扱われないように、必ず最後の指定にする必要があります)。
※ 「eol=」指定は1つ・1文字しか指定できないため、複数の種類を指定したい場合はForを重ねたり、「特定の文字で始まる行を除外したい」場合はFindstrを組み合わせたりする必要があります(その応用例は「サンプル10」にあります)。

なお、<pattern> に文字列を指定する場合、文字列の中に改行文字が含まれていてもそれは半角のスペースとして扱われてしまいます(delimsで区切り文字に半角スペースを使うと分割されます)。そのため、複数行の文字列を指定するには以下のように「^」文字を使う必要があります。またその際、「usebackq」を使用しないと「^」文字が「" "」内部の文字と扱われて効果を発揮しなくなります。

for /f "usebackq tokens=1,2 delims=:" %A in ('C1:Flower^

C2:Bird^

C3:Wind^

C4:Moon') do echo The value for key '%A' is '%B'.

※ 「^」の後ろに改行が2つ必要です。詳しくは「^」文字のページを参照してください。

<pattern> にコマンドラインを指定する場合、シングルクオーテーション「'」やアクサングラーブ(グレイヴアクセント、バッククオート)「`」をコマンドラインに含める際には以下に注意してください。

  • 「usebackq」がない場合は「')」(シングルクオーテーションと閉じ括弧)が、「usebackq」がある場合は「`)」(アクサングラーブと閉じ括弧)が、コマンドラインの終端を表す文字として扱われます。そのため、「')」や「`)」がコマンドラインの中に入る場合は「^」を用いて「'^)」や「`^)」と記述します。
  • 上記以外の「'」や「`」は閉じ記号として扱われないため、「'」や「`」の手前に「\」や「^」を付ける必要はなく、「''」や「``」のように2文字続けて記述する必要もありません。「'」や「`」1文字がそのままコマンドラインの一部として扱われます。
  • Forをコマンドラインに指定することもできますが、内部のForで /F を使い、その解析対象のコマンドラインに「( )」を用いる場合は「^^^)」のように(「^」が孫のコマンドに渡るように)「^」を重ねる必要があります。
  • 標準出力(STDOUT)に出力される内容のみが解析対象になり、標準エラー出力(STDERR)に出力される内容はそのまま流されます(通常の場合画面出力されます)。標準エラー出力を解析対象に含めたり出力されないようにしたりする場合は「>」リダイレクションをコマンド内に含める必要があります。ただし「' '」の中では「^」を用いて「>」をエスケープする(「2^>&1」や「2^>NUL」などと書く)必要があります。

上記の点を踏まえると、以下のように三重にForコマンドを使う(ネストする)ことも可能です。

for /f "tokens=1,2 delims=?" %A in ('for /f "delims=" %X in ('for /f "delims=" %Y in ('dir /b'^^^) do @echo %~fY'^) do @echo %~X?%~zX') do @echo %~nxA, %B

サンプル1

for %d in (*.dll) do regsvr32.exe /u "%d"

現在のディレクトリにあるすべての DLL ファイルに対して regsvr32.exe を実行し、COM DLL の登録削除を行います。

サンプル2 (バッチファイル)

@echo off
for %%f in (*.*) do echo %%f

現在のディレクトリにあるすべてのファイル(ディレクトリおよび隠しファイル・システムファイルを除く)を画面に表示します。

サンプル3

for /L %n in (8,-3,1) do @echo %n

[Windows NT系] [拡張構文] 画面には「8」「5」「2」が出力されます。

サンプル4

for /L %n in (1,1,%NUMBER_OF_PROCESSORS%) do hoge.exe %n

[Windows NT系] [拡張構文] 使用できる(論理)プロセッサーの数だけ「hoge.exe」を実行し、引数に何番目かを指定します。(「NUMBER_OF_PROCESSORS」はOSが設定している環境変数です。)

サンプル5

for /F "tokens=1,2,*" %1 in ("This is a pen.") do @echo "%1" "%2" "%3"

[Windows NT系] [拡張構文] 「/F」によりテキストの解析を行います。「tokens」オプションを使うことで、「%1」の他に「%2」と「%3」(「*」の指定により「%1」と「%2」に入らなかった残り全部が入ります)の変数が用意されています。これを実行すると、画面には「"This" "is" "a pen."」が出力されます。

サンプル6

for /F "tokens=2,3 delims=/" %p in ("%DATE%") do @echo %p%q

[Windows NT系] [拡張構文] 日付のうち「月」と「日」をつなげて出力します(システムの設定が「yyyy/mm/dd」形式の場合)。

サンプル7

for /F "usebackq delims=" %t in ("D:\My Files\hoge.txt") do @foo.exe "%t"

[Windows NT系] [拡張構文] 「D:\My Files\hoge.txt」の各行の内容を引数として「foo.exe」を実行します。ファイル名にスペースが含まれているため、「usebackq」オプションを使っています。なお、「delims=」でオプションを終えているため、%t には1行のデータが丸々入ります。

サンプル8

for /F "delims=" %F in ('dir /A /B') do @echo %~fF

[Windows NT系] [拡張構文] 現在のディレクトリに存在するディレクトリとファイルすべてをフルパスで画面に出力します。Dirコマンドの「/A」スイッチによりディレクトリや隠しファイル・システムファイルも含めて列挙され、「/B」スイッチによってそれらがファイル名のみ1行に1つずつ出力されるため、Forの「%F」にはそれらのファイル名が入るようになります。なお、「%~fF」とすることで(%Fに入っていた)ファイル名がフルパスになります(「%」を参照)。

※ ディレクトリを除いて隠しファイル・システムファイルを含めたい場合は「dir /A:-D /B」と指定します。

サンプル9 (バッチファイル)

for /F "tokens=1,2 delims=," %%p in ('tasklist /FO CSV /NH') do (
    if /i "%%~p"=="explorer.exe" echo %%~q: %%~p
)

[Windows NT系] [拡張構文]tasklist /FO CSV /NH」の実行による出力(現在実行中のプロセス一覧をCSV形式で出力)を「,」で区切り、その中で1番目のトークン(この場合はプロセス名)が「explorer.exe」に一致するもののみ、1番目と2番目(この場合はプロセスID)のトークンを出力しています。なお、「%~p」とすることでダブルクオーテーション「" "」を取り除いています。

※ バッチファイルのため「%」を重ねています。

サンプル10

for /F "tokens=1,2 delims=?" %a in ('^(for /R %x in ^(*.cpp^) do echo %~tx?%x?^) ^| findstr /r "^200[0-4]" ^| sort') do @echo %b : %a

[Windows NT系] [拡張構文] 現在のディレクトリとそのサブディレクトリすべてにある「*.cpp」ファイルを検索し、その中で更新日時が2000年~2004年であるファイルを古い順にすべて表示します。目的の結果を得るために、For「/F」で指定するコマンドの中にForとパイプを用いています(正しく解釈させるために「^」文字も使用します)。

まず、最初のForにおける「in」以降の括弧内で以下のコマンドを実行しています。

(for /R %x in (*.cpp) do echo %~tx?%x?) | findstr /r "^200[0-4]" | sort

このコマンドにおけるForで、現在のディレクトリとそのサブディレクトリすべてにある「*.cpp」を検索、Echoコマンドでその更新日時(「%~tx」)とファイル名を「?」文字区切りで出力します。このForコマンドにおける出力例は以下の通りです。

2013/06/30?G:\My Sources\Project1\hello.cpp?
2004/02/29?G:\My Sources\ProjectArchive\Hoge1\file1.cpp?
2003/01/30?G:\My Sources\ProjectArchive\Hoge1\file2.cpp?
2012/10/05?G:\My Sources\Temp\temp.cpp?

※ Forによる出力結果全体を次のコマンドに渡すため、Forの外側に「( )」が必要です。

つづいて、Findstrコマンドで「2000, 2001, 2002, 2003, 2004」のいずれかで始まる文字列を抽出します(Findstrで使用可能な正規表現「^200[0-4]」を用いています)。その結果は以下の通りです。

2004/02/29?G:\My Sources\ProjectArchive\Hoge1\file1.cpp?
2003/01/30?G:\My Sources\ProjectArchive\Hoge1\file2.cpp?

そして、Sortコマンドで昇順に並び替えるので出力が以下の通り変わります。

2003/01/30?G:\My Sources\ProjectArchive\Hoge1\file2.cpp?
2004/02/29?G:\My Sources\ProjectArchive\Hoge1\file1.cpp?

以上の出力結果を、外側のFor「/F」スイッチに解釈させます。一連のコマンドの中にパイプや括弧が含まれるため、外側のForなどに解釈されないようにそれらの文字の前に「^」を付けて記述します。

外側のForを使って解析すると、最終的に以下の出力が得られます。

G:\My Sources\ProjectArchive\Hoge1\file2.cpp : 2003/01/30
G:\My Sources\ProjectArchive\Hoge1\file1.cpp : 2004/02/29

なお、外側のForでは(結果的に)「%b」に有効なファイル名が入るため、「%~nxb」とすればディレクトリ名を除いたファイル名、「%~zb」とすればそのファイルのサイズを得ることができます。

※ バッチファイルでForの中にForを記述する場合、内部のForで宣言する %変数 (この例の場合は「%x」)を「%%%%x」などと記述する必要はなく、従来のバッチファイルでの変数利用と同様の記法「%%x」で問題ありません。

サンプル11 (バッチファイル)

@echo off
setlocal enabledelayedexpansion
set TEMPLATE_FILE=D:\Data\Template\hoge.xml
set OUT_FILE=D:\MyData\bar.xml
set MY_VERSION=123

type NUL > "%OUT_FILE%"
for /F "usebackq delims=" %%t in ("%TEMPLATE_FILE%") do (
    set TEMP_LINE=%%t
    set TEMP_LINE=!TEMP_LINE:[version]=%MY_VERSION%!
    echo !TEMP_LINE!>> "%OUT_FILE%"
)

[Windows NT系] [拡張構文] テンプレートファイル「D:\Data\Template\hoge.xml」をベースにファイル「D:\MyData\bar.xml」を作成しますが、その際「D:\Data\Template\hoge.xml」に「[version]」という記述が含まれていた場合、それを「MY_VERSION」の変数の値(この場合は「123」)に置き換えます。8行目では一旦出力ファイルの中身を空にし、12行目で変換されたデータをファイルに追加出力しています。

なお、「[version]」文字列を置き換えるために行の内容を一旦仮の変数に設定し、「%」で使用できる拡張された展開方法を用いて文字列を置き換えたのち、その内容をファイルに出力していますが、Forのコマンドライン内で変数を作成・書き換えおよび使用するため、「!」による遅延環境変数展開機能を用いています(「!」を「%」にすると意図した動作が得られません)。

※ この例では「hoge.xml」はShift JISで記述されている必要があり、日本語文字が含まれたUTF-8形式などの場合「bar.xml」が文字化けする場合があります。UTF-8形式で読み書きする例はChcpコマンドの例をご覧ください。

関連項目