連載
» 2001年06月23日 00時00分 公開

Windows 2000 活用講座 Windows 2000 コマンドライン徹底活用:第8回 forコマンド(その2) (1/2)

GUIだけでは面倒な定型処理なども、コマンドラインを使えば効率よく作業できる。今回は、繰り返し処理を行うfor文を解説。

[塩田紳二,著]
Windows 2000 活用講座 Windows 2000 コマンドライン徹底活用
Windows Server Insider


「Windows 2000 活用講座 Windows 2000 コマンドライン徹底活用」のインデックス

連載目次

 前回はforステートメントの基本的な使い方を解説したが、今回は、forステートメントの拡張された機能について解説する。

 コマンド プロンプトで利用できる多くのステートメントは、MS-DOS以来使われてきた基本的なバッチ言語の機能に加えて、Windows NTやWindows 2000ではその機能が大幅に強化され使いやすくなっている。そして、さらに「コマンド拡張機能」と呼ばれる機能も用意され、よりいっそう便利に使えるようになっている。例えば、カレントディレクトリを変更する“cd”コマンドでは、Windows 9xなどでは空白を含むディレクトリ名を指定する場合は、必ずダブルクォート(“"”)で囲む必要があったが、コマンド拡張機能が有効な場合には、ダブルクォートで囲まなくてもすむようになっている(例:「cd \Program files\Accessories」のように入力できる)。このコマンド拡張機能は、従来のコマンドの機能と比べると、オプションの意味やデフォルト動作などが変わっていることも多いので、混乱を防ぐために、cmd.exeを起動する際のオプションとしてその有効/無効を指定できるようになっている(デフォルトではこれはオンになっている)。なおWindows NTと2000では拡張機能に違いがあるが、ここではWindows 2000について解説を行うことにする。

 今回は、forコマンドで利用できる拡張機能について解説する。


 forステートメントで利用できる拡張機能としては、前回紹介した変数の修飾子による展開のほかにも、さまざまな繰り返し機能の強化などがある。MS-DOSのforコマンドでは、あるフォルダ中にあるファイルを一括指定して、それらに対して何らかの処理を行うことしかできなかったが、forの拡張機能では、「あるディレクトリのみを処理対象とする」、「再帰的にディレクトリ・ツリーを検索する」、「数値による繰り返し処理を行う」、「ファイル解析による繰り返し処理を行う」の4つの機能が利用できる。

ディレクトリを扱う

 forコマンドにオプションとして“/D”を付けると、ワイルドカード指定で取り出されるものはディレクトリのみになる。

C:\cmd>dir
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は A024-5237 です

C:\cmd のディレクトリ

2001/04/30  23:43       <DIR>          .
2001/04/30  23:43       <DIR>          ..
2001/03/09  01:00                  303 backupD.cmd
2001/01/07  02:05       <DIR>          dr20001200
2001/01/07  02:11       <DIR>          dr20010107
2001/02/12  04:49       <DIR>          Dr20010212
2001/04/23  04:05       <DIR>          dr20010422
2001/04/22  04:17                    3 y.txt
               2 個のファイル                 306 バイト
               6 個のディレクトリ  20,474,318,848 バイトの空き領域

C:\cmd>

というディレクトリで、以下のようなスクリプトを使って/Dオプションのあり/なしでforコマンドを実行してみる。

ファイル:for-d01.cmd

@echo off
echo ---- /D Option ----
for /D %%i in ( *.* ) do echo %%i
echo ---- No /D Option ----
for %%i in ( *.* ) do echo %%i


 実行結果は以下のようになる。

C:\cmd>for-d01.cmd
---- /D Option ----
dr20001200    ……ディレクトリのみが表示されている
dr20010107
Dr20010212
dr20010422
dr20010613
---- No /D Option ----
backupD.cmd    ……ファイルのみが表示されている
y.txt

 この結果からすぐに思いつくのは、forコマンドをディレクトリを対象とするコマンドに適用することであるが、この“/D”オプションだけでは、カレントディレクトリか、“/D”オプション直後に指定したディレクトリのみが選択の対象となる。

 これとは別に、指定ディレクトリ以下のすべてのディレクトリを対象とするオプションとして“/R”が用意されている。この2つを組み合わせることで、カレントディレクトリ以下のすべてのディレクトリのみを取り出すことが可能となる。

 それでは、先ほどのスクリプトに“/R”を付加してみよう。

ファイル:for-d02.cmd

@echo off
echo ---- /D Option ----
for /R /D %%i in ( *.* ) do echo %%i
echo ---- No /D Option ----
for /R %%i in ( *.* ) do echo %%i

これを実行してみると、

C:\cmd>for-d02.cmd
---- /D Option ----
C:\cmd\dr20001200  ……ディレクトリが再帰的に表示されている
C:\cmd\dr20010107
C:\cmd\Dr20010212
C:\cmd\dr20010422
C:\cmd\dr20010613
C:\cmd\Dr20010212\abc
C:\cmd\Dr20010212\bbb
C:\cmd\dr20010422\testdir
C:\cmd\dr20010422\testdir\t1
C:\cmd\dr20010422\testdir\t2
---- No /D Option ----
C:\cmd\backupD.cmd  ……ファイルが再帰的に表示されている
C:\cmd\y.txt
C:\cmd\dr20001200\fortest01.bat
C:\cmd\dr20001200\fortest02.bat
     :
     :
   途中省略
     :
     :

C:\cmd\dr20010422\testdir\t2\ZZPP0007.JPG
C:\cmd\dr20010613\for-d01.cmd
C:\cmd\dr20010613\for-d02.cmd

“/R”と“/D”を指定すると、ディレクトリのみが再帰的に取り出され、それが変数に代入されていく。“/R”のみでは、ディレクトリ以下のすべてのファイルが列挙される。

 また、もう1つの使い方として、“/R”のみを指定し、ワイルドカードの代わりに“.”を指定すると、“/R /D”を指定したのとほとんど同じになる。Windows 2000コマンドリファレンスには、「set がピリオド (.) 1 文字だけの場合は、ディレクトリ ツリーの列挙だけを行います。」と記述してあるので、以下のスクリプトで実際に試してみよう。

ファイル:for-d03.cmd

@echo off
echo ---- /D Option ----
for /R /D %%i in ( *.* ) do echo %%i
echo ---- No /D Option and "." ----
for /R %%i in ( . ) do echo %%i

 これを実行すると、以下のようになる。

C:\cmd>for-d03.cmd
---- /D Option ----
C:\cmd\dr20001200  ……ディレクトリが再帰的に表示されている
C:\cmd\dr20010107
C:\cmd\Dr20010212
C:\cmd\dr20010422
C:\cmd\dr20010613
C:\cmd\Dr20010212\abc
C:\cmd\Dr20010212\bbb
C:\cmd\dr20010422\testdir
C:\cmd\dr20010422\testdir\t1
C:\cmd\dr20010422\testdir\t2
---- No /D Option and "." ----
C:\cmd\.
C:\cmd\dr20001200\. …やはりディレクトリが再帰的に表示されている
C:\cmd\dr20010107\.  ただし表示される順番は若干異なっている
C:\cmd\Dr20010212\.
C:\cmd\Dr20010212\abc\.
C:\cmd\Dr20010212\bbb\.
C:\cmd\dr20010422\.
C:\cmd\dr20010422\testdir\.
C:\cmd\dr20010422\testdir\t1\.
C:\cmd\dr20010422\testdir\t2\.
C:\cmd\dr20010613\.
C:\cmd>

 この2つのコマンドの実行結果はほぼ同じだが(ただし順番は少し違う)、注意すべきは、戻ってくる値の最後の部分である。“/R”と“.”を使った場合、各フォルダにある“.”というディレクトリ、つまり自分自身を表すディレクトリ記号を探すことになり、変数に代入される文字列の最後の部分は“\.”となっている。このため、ディレクトリ名を使って処理を行うような場合には、“/R /D”を指定したほうが、文字列処理が煩雑にならずにすむだろう。

 実際にこれらの機能を利用する場合、例えば特定の名前のファイルに対して、ディレクトリを再帰的にたどりつつ、処理するといった使い方などがありえるだろう。あるいは、findコマンドなどと組み合わせて、特定の文字列を含むファイルを探すといった用途にも利用できる。

 例えばファイル同士を比較するcompコマンドと組み合わせて利用すると、指定したディレクトリ以下のすべてのファイルとの比較を行い、内容が一致するファイルを見つけることが可能になる。

ファイル:for-comp01.cmd

@echo off
echo N> $$$N
for /R %%i in ( *.* ) do comp %1 %%i <$$$N 2>&1 | Find "違いはありません" >NUL && echo %1 == %%i
del $$$N

 compコマンドは、与えられた2つの引数をファイルとしてオープンし、その内容が同じかどうかを調べるコマンドである。もともとインタラクティブに使うことを想定しているためか、比較が終わると別のファイルを処理するかどうかを聞いてくる。それでは困るので、ここでは、“N”という文字の入ったファイルを作り(2行目)、それをcompコマンドの入力としている。これにより、ファイルを1つ比較するだけですぐに終了する。また、このときの質問文が標準エラー出力に出てしまって煩わしいので、これを標準出力へリダイレクトさせている(3行目の“2>&1”)。もし、ファイルの内容が一致していれば「ファイルに違いはありません」という文字列が出力されるため、これをfindコマンドで検出させ、見つかった時だけ、後続のechoステートメントを実行させる。これには“&&”を使っている。“&&”は、直前のコマンドが失敗しなければ(成功すれば)その右側にあるコマンドを実行させるという意味の記号である。findコマンドでは、指定された文字列を見つけたときのみ成功したことになるので、これでファイルを発見したことを検出できるのである。

 実行例は、以下のようになる

C:\cmd>for-comp01.cmd org.txt
org.txt == C:\cmd\org.txt ……org.txtと同じ内容を持つファイルが2つあった
org.txt == C:\cmd\dr20010422\testdir\t2\T.txt

 なお以前説明したように、単に“N”のみを含むファイルを作っておけば、前後のステートメントを省略可能である。

数値による繰り返し

 forコマンドのもう1つの機能として、数値による繰り返し処理を行うというものがある。これは、通常のプログラミング言語、例えば、BASIC言語などで使われる繰り返しに近いものだ。

 書式としては、

for /L %%i in ( start , step , end ) do コマンド

となり、“/L”オプションを付け、ファイル名のセットの代わりに3つの数字をカンマで区切って指定する。この3つの数値は、それぞれ繰り返しの「初期値(start)」、「ステップ値(step)」、「終値(end)」となる。例えばこれを“1,1,10”と指定すると、変数には、1から10までの数値(1、2、3、4、5、6、7、8、9、10)が順次変数iに代入されて[コマンド]部分が実行される。

 これは、(回数が決まっている)単純な繰り返しか、数値を引数とするような処理(例えば、ファイル名の一部が数字でできているような場合)に利用することができるが、ファイルを直接対象とする他の形式と比べるとちょっと利用頻度が低いかもしれない。

 それではさっそく実行させてみよう。コマンドプロンプトから“for /L %i in ( 4、-1、1) do echo %i”と入力してみれば、ちゃんと変数が4、3、2、1と代入されつつ、echoコマンドが実行されるのが分かるだろう。

C:\cmd>for /L %i in ( 4,-1,1) do echo %i

C:\cmd>echo 4
4

C:\cmd>echo 3
3

C:\cmd>echo 2
2

C:\cmd>echo 1
1

C:\cmd>

 このような数値列を使って、さらに数値計算を行わせることも不可能ではない。setコマンドは、“/A”オプションを付けることで計算を行わせることが可能である(Windows 2000のヘルプファイルにはこの記述はないが、コマンドプロンプト上で“set /?”を実行すれば、その方法が表示される)。以下のようなforステートメントを直接コマンドプロンプトから実行させることで、1〜10までの数の和を求めることが可能だ。

set a=0 & for /L %i in ( 1,1,10 ) do set /a a=a+%i

以下はその実行例である。

C:\cmd>set a=0 & for /L %i in ( 1,1,10 ) do set /a a=a+%i

C:\cmd>set /a a=a+1
1
C:\cmd>set /a a=a+2
3
C:\cmd>set /a a=a+3
6
   :
   :
 途中省略
   :
   :
C:\cmd>set /a a=a+9
45
C:\cmd>set /a a=a+10
55
C:\cmd>echo %A%   ………変数Aを表示させてみる
55

 このように、繰り返しによる数値計算もできなくもない。ただし、setコマンドによる計算は、整数演算だけなので注意されたい。


       1|2 次のページへ

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。