今はもうOSに標準でPowerShellが搭載されている時代です。Windows 2000世代からはWSHが標準搭載されバッチファイルから解放されました。Windows 7, Windows Server 2008ではPowerShellが標準搭載されWSHからも解放されました。.net frameworkも使いつつオブジェクト指向のスクリプトが書ける、そんないい時代になりました。めでたしめでたし…とはいかないのがこの業界です。残念ながら最新のOS上でいまだにバッチファイルを書かなければならない仕事、未だに仮想化されたWindowsNTの面倒を見なければいけない仕事などが存在するのが現実です。

バッチファイルでは実際のところ相当生産性が低いのですが、そんな中で異彩を放つコマンド”for”。その名前からはただの繰り返しコマンドに思えるのですが、実は恐ろしい力を秘めています。実際の所バッチファイルでちょっと複雑なことをやろうと思うとforを効果的に使わないといけません。今回は未だにバッチファイルを書かなければいけない不幸な人のためにforコマンドのTips集をお届けします。

forコマンドのヘルプから読み取れる「できること」

forコマンドは色々な事ができるコマンドなのですが、まじまじとヘルプを見たことが無い人も多いと思います。以下はWindows7のforコマンドのヘルプです。

 

 

FOR%IN()DO[]

 

 

%

 

()使

 

 

 

 

 

FOR使%

 

%%使

 

%i%I

 

 

FOR

 

:

 

 

FOR/D%IN()DO[]

 

 

 

 

 

FOR/R[[:]]%IN()DO[]

 

 

[:]FOR

 

/R

 

使

 

 

 

FOR/L%IN(,,)DO[]

 

 

 

(1,1,5)12345(5,-1,1)(54321)

 

 

 

FOR/F[""]%IN()DO

 

[]

 

FOR/F[""]%IN("")DO[]

 

FOR/F[""]%IN'')DO[]

 

 

usebackq:

 

 

FOR/F[""]%IN()DO

 

[]

 

FOR/F[""]%IN'')DO[]

 

FOR/F[""]%IN(``)DO[]

 

 

1

 

 

0

 

 

for/F

 

 

""

 

1

 

:

 

 

eol=c-(1)

 

skip=n-

 

delims=xxx-

 

 

 

tokens=x,y,m-n-for

 

 

 

m-nmn

 

 

tokens=

 

 

 

usebackq-

 

 

 

 

 

 

:

 

 

FOR/F"eol=;tokens=2,3*delims=,"%iin(myfile.txt)do@echo%i%j%k

 

 

myfile.txt

 

23for

 

 

for%i2%j3

 

%k3

 

 

 

 

使usebackq

 

使

 

使

 

 

 

%ifor%j%ktokens=

 

 

tokens=使26

 

'z''Z'FOR

 

 

52

 

 

 

FOR/F使

 

 

 

FOR/F使

 

 

CMD.EXE

 

 

:

 

 

FOR/F"usebackqdelims=="%iIN(`set`)DO@echo%i

 

 

 

 

FOR

 

使:

 

 

%~I-(")%I

 

%~fI-%I

 

%~dI-%I

 

%~pI-%I

 

%~nI-%I

 

%~xI-%I

 

%~sI-

 

%~aI-%I

 

%~tI-%I/

 

%~zI-%I

 

%~$PATH:I-PATH

 

%I

 

 

 

 

 

 

:

 

 

%~dpI-%I

 

%~nxI-%I

 

%~fsI-%I

 

%~dp$PATH:I-PATH

 

%I

 

 

%~ftzaI-%IDIR

 

 

%IPATH

 

%~FOR%I

 

使

 

 

ヘルプの長さにまず驚かされますが、「指定されたコマンドをファイル セットの各ファイルに対して実行します。」と、ある通り、基本的には複数のファイルに対してコマンドを実行することが出来るコマンドということになっているようです。

FOR/D%IN()DO[]

 

 

 

 

さらに上記のようにディレクトリに対しても処理を行えることがわかります。

FOR/R[[:]]%IN()DO[]

 

 

[:]FOR

 

/R

 

使

 

 

ディレクトリツリーに対して再帰的に処理も行えるようです。

FOR/L%IN(,,)DO[]

 

 

 

(1,1,5)12345(5,-1,1)(54321)

 

 

もちろん普通のプログラム言語のように数を変化させながら繰り返し処理もできます。

FOR/F[""]%IN()DO

 

[]

 

FOR/F[""]%IN("")DO[]

 

FOR/F[""]%IN'')DO[]

 

 

usebackq:

 

 

FOR/F[""]%IN()DO

 

[]

 

FOR/F[""]%IN'')DO[]

 

FOR/F[""]%IN(``)DO[]

 

文字列やコマンドの結果に対しても処理ができちゃいます。

1

 

 

0

 

 

for/F

 

 

 

さらにファイルに対してはその内容を読み取り行ごとに処理したり、さらに”トークンへの解析”までしてくれちゃいます。

""

 

1

 

:

 

 

eol=c-(1)

 

skip=n-

 

delims=xxx-

 

 

 

tokens=x,y,m-n-for

 

 

 

m-nmn

 

 

tokens=

 

 

 

usebackq-

 

 

 

 

 

コメント文字の指定や、スキップする行数の指定まで出来ますし、区切り文字の指定、本体に渡すトークン指定までできちゃいます。

FOR

 

使:

 

 

%~I-(")%I

 

%~fI-%I

 

%~dI-%I

 

%~pI-%I

 

%~nI-%I

 

%~xI-%I

 

%~sI-

 

%~aI-%I

 

%~tI-%I/

 

%~zI-%I

 

%~$PATH:I-PATH

 

%I

 

 

 

 

 

 

:

 

 

%~dpI-%I

 

%~nxI-%I

 

%~fsI-%I

 

%~dp$PATH:I-PATH

 

%I

 

 

%~ftzaI-%IDIR

 

さらにさらに変数の置換機能まであります。

 

…。さすがはforコマンドですね。「それは別のコマンドを用意したほうがいいんじゃないのか?」という機能まで満載されています。コマンドプロンプト、バッチファイルでは他の機能が貧弱なだけにforコマンドを多用することになります。

では、いくつか例を実行してみたいと思います。この手のものは「習うより慣れろ」ですから是非コマンドプロンプトを立ち上げて一緒に操作しながら読んでもらえればと思います。

ループ処理

まずは、テスト用のディレクトリを作成します。

1:mkdirc:\fortest

 

2:cdc:\fortest

 

テスト用のテキストファイルを用意しましょう。適当に10個程度にしましょうか。せっかくですのでこれもforコマンドで作成してみましょう。

以下のように実行すると10個のテキストファイルが生成されます。

1:c:\fortest>for/L%iIN(1,1,10)DOechosample%i>sample%i.txt

 

2:

 

3:c:\fortest>echosample11>sample1.txt

 

4:

 

5:c:\fortest>echosample21>sample2.txt

 

6:

 

7:c:\fortest>echosample31>sample3.txt

 

8:

 

9:c:\fortest>echosample41>sample4.txt

 

10:

 

11:c:\fortest>echosample51>sample5.txt

 

12:

 

13:c:\fortest>echosample61>sample6.txt

 

14:

 

15:c:\fortest>echosample71>sample7.txt

 

16:

 

17:c:\fortest>echosample81>sample8.txt

 

18:

 

19:c:\fortest>echosample91>sample9.txt

 

20:

 

21:c:\fortest>echosample101>sample10.txt

 

/Lオプションを使用するとこのように変数の中に数字を入れつつ、コマンドを繰り返し実行させることができます。この例では変数%iに対して1から1つづつ値をふやしながら10になるまで「echo sample%1 > sample%i.txt」というコマンドを実行させています。これはいわゆるプログラム言語でいうところのfor文と同じような感じなので理解しやすいのではないかと思います。

ファイル名の取得

次はファイル名の取得の例です。以下のように実行できます。

1:c:\fortest>for%iIN.txt)DO@echo%i

 

2:sample1.txt

 

3:sample10.txt

 

4:sample2.txt

 

5:sample3.txt

 

6:sample4.txt

 

7:sample5.txt

 

8:sample6.txt

 

9:sample7.txt

 

10:sample8.txt

 

11:sample9.txt

 

オプションを付けずにforを実行すると、パターンにマッチするファイル名を取得して変数に1つづつ値を入れつつ、コマンドを実行させることができます。このパターンマッチにはディレクトリ(フォルダ)はマッチしません。以下のように確認できます。

1:c:\fortest>for/L%iIN(1,1,10)DOmkdirdir%i

 

2:

 

3:c:\fortest>mkdirdir1

 

4:

 

5:c:\fortest>mkdirdir2

 

6:

 

7:c:\fortest>mkdirdir3

 

8:

 

9:c:\fortest>mkdirdir4

 

10:

 

11:c:\fortest>mkdirdir5

 

12:

 

13:c:\fortest>mkdirdir6

 

14:

 

15:c:\fortest>mkdirdir7

 

16:

 

17:c:\fortest>mkdirdir8

 

18:

 

19:c:\fortest>mkdirdir9

 

20:

 

21:c:\fortest>mkdirdir10

 

22:

 

23:c:\fortest>for%iINDO@echo%i

 

24:sample1.txt

 

25:sample10.txt

 

26:sample2.txt

 

27:sample3.txt

 

28:sample4.txt

 

29:sample5.txt

 

30:sample6.txt

 

31:sample7.txt

 

32:sample8.txt

 

33:sample9.txt

 

34:

 

35:c:\fortest>dir

 

36:C

 

37:C0AF-1B4F

 

38:

 

39:c:\fortest

 

40:

 

41:2012/03/1521:59

 

42:2012/03/1521:59

 

43:2012/03/1521:59dir1

 

44:2012/03/1521:59dir10

 

45:2012/03/1521:59dir2

 

46:2012/03/1521:59dir3

 

47:2012/03/1521:59dir4

 

48:2012/03/1521:59dir5

 

49:2012/03/1521:59dir6

 

50:2012/03/1521:59dir7

 

51:2012/03/1521:59dir8

 

52:2012/03/1521:59dir9

 

53:2012/03/1521:5510sample1.txt

 

54:2012/03/1521:5511sample10.txt

 

55:2012/03/1521:5510sample2.txt

 

56:2012/03/1521:5510sample3.txt

 

57:2012/03/1521:5510sample4.txt

 

58:2012/03/1521:5510sample5.txt

 

59:2012/03/1521:5510sample6.txt

 

60:2012/03/1521:5510sample7.txt

 

61:2012/03/1521:5510sample8.txt

 

62:2012/03/1521:5510sample9.txt

 

63:10101

 

64:12142,859,378,688

 

ディレクトリ名の取得

/Dオプションをつけて実行すると、ディレクトリのみがパターンにマッチするようになります。

1:c:\fortest>for/D%iINDO@echo%i

 

2:dir1

 

3:dir10

 

4:dir2

 

5:dir3

 

6:dir4

 

7:dir5

 

8:dir6

 

9:dir7

 

10:dir8

 

11:dir9

 

再帰処理

ディレクトリを指定し、そこから下位のディレクトリのそれぞれでforコマンドを実行させることができます。ちょっとディレクトリ、ファイルを準備してみます。

1:c:\fortest>for/L%iIN(1,1,10)DOechosample%i>\dir%i\sample%i.txt

 

2:

 

3:c:\fortest>echosample11>.\dir1\sample1.txt

 

4:

 

5:c:\fortest>echosample21>.\dir2\sample2.txt

 

6:

 

7:c:\fortest>echosample31>.\dir3\sample3.txt

 

8:

 

9:c:\fortest>echosample41>.\dir4\sample4.txt

 

10:

 

11:c:\fortest>echosample51>.\dir5\sample5.txt

 

12:

 

13:c:\fortest>echosample61>.\dir6\sample6.txt

 

14:

 

15:c:\fortest>echosample71>.\dir7\sample7.txt

 

16:

 

17:c:\fortest>echosample81>.\dir8\sample8.txt

 

18:

 

19:c:\fortest>echosample91>.\dir9\sample9.txt

 

20:

 

21:c:\fortest>echosample101>.\dir10\sample10.txt

 

22:

 

23:c:\fortest>dir/s

 

24:C

 

25:C0AF-1B4F

 

26:

 

27:c:\fortest

 

28:

 

29:2012/03/1521:59

 

30:2012/03/1521:59

 

31:2012/03/1522:05dir1

 

32:2012/03/1522:05dir10

 

33:2012/03/1522:05dir2

 

34:2012/03/1522:05dir3

 

35:2012/03/1522:05dir4

 

36:2012/03/1522:05dir5

 

37:2012/03/1522:05dir6

 

38:2012/03/1522:05dir7

 

39:2012/03/1522:05dir8

 

40:2012/03/1522:05dir9

 

41:2012/03/1521:5510sample1.txt

 

42:2012/03/1521:5511sample10.txt

 

43:2012/03/1521:5510sample2.txt

 

44:2012/03/1521:5510sample3.txt

 

45:2012/03/1521:5510sample4.txt

 

46:2012/03/1521:5510sample5.txt

 

47:2012/03/1521:5510sample6.txt

 

48:2012/03/1521:5510sample7.txt

 

49:2012/03/1521:5510sample8.txt

 

50:2012/03/1521:5510sample9.txt

 

51:10101

 

52:

 

53:c:\fortest\dir1

 

54:

 

55:2012/03/1522:05

 

56:2012/03/1522:05

 

57:2012/03/1522:0510sample1.txt

 

58:110

 

59:

 

60:c:\fortest\dir10

 

61:

 

62:2012/03/1522:05

 

63:2012/03/1522:05

 

64:2012/03/1522:0511sample10.txt

 

65:111

 

66:

 

67:c:\fortest\dir2

 

68:

 

69:2012/03/1522:05

 

70:2012/03/1522:05

 

71:2012/03/1522:0510sample2.txt

 

72:110

 

73:

 

74:c:\fortest\dir3

 

75:

 

76:2012/03/1522:05

 

77:2012/03/1522:05

 

78:2012/03/1522:0510sample3.txt

 

79:110

 

80:

 

81:c:\fortest\dir4

 

82:

 

83:2012/03/1522:05

 

84:2012/03/1522:05

 

85:2012/03/1522:0510sample4.txt

 

86:110

 

87:

 

88:c:\fortest\dir5

 

89:

 

90:2012/03/1522:05

 

91:2012/03/1522:05

 

92:2012/03/1522:0510sample5.txt

 

93:110

 

94:

 

95:c:\fortest\dir6

 

96:

 

97:2012/03/1522:05

 

98:2012/03/1522:05

 

99:2012/03/1522:0510sample6.txt

 

100:110

 

101:

 

102:c:\fortest\dir7

 

103:

 

104:2012/03/1522:05

 

105:2012/03/1522:05

 

106:2012/03/1522:0510sample7.txt

 

107:110

 

108:

 

109:c:\fortest\dir8

 

110:

 

111:2012/03/1522:05

 

112:2012/03/1522:05

 

113:2012/03/1522:0510sample8.txt

 

114:110

 

115:

 

116:c:\fortest\dir9

 

117:

 

118:2012/03/1522:05

 

119:2012/03/1522:05

 

120:2012/03/1522:0510sample9.txt

 

121:110

 

122:

 

123::

 

124:20202

 

125:32142,869,659,648

 

これで、カレントディレクトリにはディレクトリが10個、ファイルが10個。サブディレクトリにはそれぞれファイルが1個づつという状態になりました。現在のディレクトリ以下にある.txtという拡張子を持つファイルを全て表示してみます。

1:c:\fortest>for/R%iIN.txt)DO@echo%i

 

2:c:\fortest\sample1.txt

 

3:c:\fortest\sample10.txt

 

4:c:\fortest\sample2.txt

 

5:c:\fortest\sample3.txt

 

6:c:\fortest\sample4.txt

 

7:c:\fortest\sample5.txt

 

8:c:\fortest\sample6.txt

 

9:c:\fortest\sample7.txt

 

10:c:\fortest\sample8.txt

 

11:c:\fortest\sample9.txt

 

12:c:\fortest\dir1\sample1.txt

 

13:c:\fortest\dir10\sample10.txt

 

14:c:\fortest\dir2\sample2.txt

 

15:c:\fortest\dir3\sample3.txt

 

16:c:\fortest\dir4\sample4.txt

 

17:c:\fortest\dir5\sample5.txt

 

18:c:\fortest\dir6\sample6.txt

 

19:c:\fortest\dir7\sample7.txt

 

20:c:\fortest\dir8\sample8.txt

 

21:c:\fortest\dir9\sample9.txt

 

ディレクトリ名だけ表示するには以下のようにします。

1:c:\fortest>for/R%iINDO@echo%i

 

2:c:\fortest\.

 

3:c:\fortest\dir1\.

 

4:c:\fortest\dir10\.

 

5:c:\fortest\dir2\.

 

6:c:\fortest\dir3\.

 

7:c:\fortest\dir4\.

 

8:c:\fortest\dir5\.

 

9:c:\fortest\dir6\.

 

10:c:\fortest\dir7\.

 

11:c:\fortest\dir8\.

 

12:c:\fortest\dir9\.

 

カレントディレクトリ(.)にだけマッチさせるような感じですね。

ファイルの中身へのアクセス

さて、次はいよいよファイルの中身へのアクセスです。これは/Fオプションで実現できます。

まず、テストのためにファイル内に10行書かれているファイルを用意します。これもfor文でやりましょう。

1:c:\fortest>for/L%iIN(1,1,10)DOecho%isample.txt

 

2:

 

3:c:\fortest>echo11>>sample.txt

 

4:

 

5:c:\fortest>echo21>>sample.txt

 

6:

 

7:c:\fortest>echo31>>sample.txt

 

8:

 

9:c:\fortest>echo41>>sample.txt

 

10:

 

11:c:\fortest>echo51>>sample.txt

 

12:

 

13:c:\fortest>echo61>>sample.txt

 

14:

 

15:c:\fortest>echo71>>sample.txt

 

16:

 

17:c:\fortest>echo81>>sample.txt

 

18:

 

19:c:\fortest>echo91>>sample.txt

 

20:

 

21:c:\fortest>echo101>>sample.txt

 

22:

 

23:c:\fortest>typesample.txt

 

24:1

 

25:2

 

26:3

 

27:4

 

28:5

 

29:6

 

30:7

 

31:8

 

32:9

 

33:10

 

このファイルの中身を1行づつ読み取ってみます。

1:c:\fortest>for/F%iIN(sample.txt)DO@echo%i

 

2:1

 

3:2

 

4:3

 

5:4

 

6:5

 

7:6

 

8:7

 

9:8

 

10:9

 

11:10

 

「type sample.txt」を実行した結果と同じ結果になるわけですが、1行づつ読み取り、それが変数%iに入れられ、それが1行づつechoされているのがわかりますでしょうか。

もうちょっとわかりやすくするために以下のようにしてみましょうか。

1:c:\fortest>for/F%iIN(sample.txt)DO@echo%i

 

2:1

 

3:2

 

4:3

 

5:4

 

6:5

 

7:6

 

8:7

 

9:8

 

10:9

 

11:10

 

あまり内容は変わっていませんが、変数の中にファイルの内容が1行づつ入っていく様子がわかるかと思います。

ちなみに/Fオプションを使っているときにはパターンマッチは行えません。つまり内容を読み込んで処理できるのは1ファイルだということです。

1:c:\fortest>for/F%iIN.txt)DO@echo%i

 

2:.txt

 

文字列の処理、コマンドの結果

上記の/Fオプションはファイルの中身に対してだけではなくて、文字列に対してやコマンドの結果に対しても同じように処理できます。

1:c:\fortest>for/F%iIN("hogehoge")DO@echo%i

 

2:hogehoge

 

これだとただ単にechoしているのと変わらないのですが(どう嬉しいのかはもうちょっと待ってください)。文字列は変数に入れておくこともできます。

1:c:\fortest>setmojiretsu=hogehoge

 

2:

 

3:c:\fortest>echo%mojiretsu%

 

4:hogehoge

 

5:

 

6:c:\fortest>for/F%iIN("%mojiretsu%")DO@echo%i

 

7:hogehoge

 

コマンドの結果を処理する場合には「’’」を使ってコマンドを囲むことで実現できます。

1:c:\fortest>for/F%iIN'ipconfig')DO@echo%i

 

2:Windows

 

3:Wireless

 

4:

 

5:

 

6:IPv4

 

7:

 

8:

 

9:

 

10:.

 

11:

 

12:Tunnel

 

13:.

 

14:

 

15:Tunnel

 

16:.

 

17:

 

18:Tunnel

 

19:

 

20:IPv6

 

21:

 

22:

 

23:Tunnel

 

24:.

 

25:

 

26:Tunnel

 

27:.

 

28:

 

おや。出力がipconfigの結果そのままではありませんね。これは規定の状態で以下のようになっているからです。(ヘルプより引用)

既定では、/F は、各ファイルの各行から、空白で区切られた最初のトークンを取得して渡します。空白行はスキップされます。 空白行はスキップされた上で、空白で区切っているわけです。もう一度単純な文字列を処理する例を見ましょう。

1:c:\fortest>for/F%iIN("hoge1hoge2")DO@echo%i

 

2:hoge1

 

文字列は空白で区切られているので1つめのトークンの”hoge1”が%iに入れられています。2つめのトークンである”hoge2”は単純に捨てられています。これも受け取りたい場合にはtokensオプションを指定します。

1:c:\fortest>for/F"tokens=*"%iIN("hoge1hoge2")DO@echo%i

 

2:hoge1hoge2

 

 

1:c:\fortest>for/F"tokens=*"%iIN'ipconfig')DO@echo%i

 

2:WindowsIP

 

3:WirelessLANadapterwlan:

 

4:DNS..:

 

5:IPv6..:fe80::8d7e:8925:9d7e:38a2%18

 

6:IPv4..:192.168.1.108

 

7:..:255.255.255.0

 

8:..:192.168.1.1

 

9:lan:

 

10:..:

 

11:DNS..:test.local

 

12:Tunneladapterisatap.jbs.local:

 

13:..:

 

14:DNS..:

 

15:Tunneladapter6TO4Adapter:

 

16:..:

 

17:DNS..:

 

18:Tunneladapter*14:

 

19:DNS..:

 

20:IPv6..:2001:0:4137:9e76:1cca:16f7:2518:641c

 

21:IPv6..:fe80::1cca:16f7:2518:641c%15

 

22:..:::

 

23:Tunneladapterisatap.{0A10F0FC-9ABB-42D0-8C73-C71B2976D3B0}:

 

24:..:

 

25:DNS..:

 

26:TunneladapterReusableMicrosoft6To4Adapter:

 

27:..:

 

28:DNS..:

 

上記の2つの例では「tokens=*」とオプションを指定することで空白で区切ることをせず、行全部を1つのトークンにするように指定しました。なので、1行全てが%iに入っています。

空白では区切りつつ、2つの別々の変数で受け取る場合には以下の用にします。

1:c:\fortest>for/F"tokens=1,2"%iIN("hoge1hoge2")DO@echo%i%j

 

2:hoge1hoge2

 

「tokens=1,2」と指定することで1番目と2番目のトークンをそれぞれ%i, %jに入力しています。%iは明示的に宣言されているのですが、%jはいきなり登場しています。これはもうこういうものだと思ってしまうしか無いと思います。%iからはじめるなら、%i, %j, %k …と順番になります。

もちろんtokenの選び方は自由です。

1:c:\fortest>for/F"tokens=1,3"%iIN("hoge1hoge2hoge3")DO@echo%i%j

 

2:hoge1hoge3

 

3:

 

上記のように1番目と3番目を取得するようなこともできます。

1:c:\fortest>for/F"tokens=1,3*"%iIN("hoge1hoge2hoge3hoge4hoge5hoge6")DO@echo%i%j-%k

 

2:hoge1hoge3-hoge4hoge5hoge6

 

上記のように*を使うとその後のすべての文字が次の変数(ここでは%k)に入ります。*の前には「,」は必要ありません。(ちょっと文法的に違和感がありますが・・・)

1:c:\fortest>for/F"tokens=1-5"%iIN("hoge1hoge2hoge3hoge4hoge5")DO@echo%i%j%k%l%m

 

2:hoge1hoge2hoge3hoge4hoge5

 

3:

 

4:c:\fortest>for/F"tokens=1,2,3,4,5"%iIN("hoge1hoge2hoge3hoge4hoge5")DO@echo%i%j%k%l%m

 

5:hoge1hoge2hoge3hoge4hoge5

 

上記のように”token=1-5”のように範囲で書くこともできます。この場合”tokens=1,2,3,4,5”と記述したのと全く同じ意味になります。

次に区切り文字です。規定では空白ですが、delimsオプションで指定することができます。

1:c:\fortest>for/F"tokens=1,2,3delims=,"%iIN("hoge1,hoge2,hoge3")DO@echo%i%j%k%l%m

 

2:hoge1hoge2hoge3%l%m

 

これは,(カンマ)で区切った例です。これを使えばCSVファイルを扱えるわけです。

CSVファイルの読み込み

簡単なCSVファイルを準備します。

1:c:\fortest>echo1-1,1-2,1-3,1-4,1-5>sample.txt

 

2:

 

3:c:\fortest>echo2-1,2-2,2-3,2-4,2-5sample.txt

 

4:

 

5:c:\fortest>echo3-1,3-2,3-3,3-4,3-5sample.txt

 

6:

 

7:c:\fortest>typesample.txt

 

8:1-1,1-2,1-3,1-4,1-5

 

9:2-1,2-2,2-3,2-4,2-5

 

10:3-1,3-2,3-3,3-4,3-5

 

このCSVを1行づつ読み込み、カンマで区切り、5つの変数にそれぞれ値を代入し、表示します。

1:c:\fortest>for/F"tokens=1,2,3,4,5delims=,"%iIN(sample.txt)DO@echo%i%j%k%l%m

 

2:1-11-21-31-41-5

 

3:2-12-22-32-42-5

 

4:3-13-23-33-43-5

 

CSVファイルにコメント行があり読み飛ばしたい時にはeolオプションが使えます。

テスト用のCSVファイルを用意します。

1:c:\fortest>echo#sample.txt

 

2:

 

3:c:\fortest>echo4-1,4-2,4-3,4-4,4-5sample.txt

 

4:

 

5:c:\fortest>typesample.txt

 

6:1-1,1-2,1-3,1-4,1-5

 

7:2-1,2-2,2-3,2-4,2-5

 

8:3-1,3-2,3-3,3-4,3-5

 

9:#

 

10:4-1,4-2,4-3,4-4,4-5

 

1:c:\fortest>for/F"tokens=1,2,3,4,5delims=,eol=#"%iIN(sample.txt)DO@echo%i%j%k%l%m

 

2:1-11-21-31-41-5

 

3:2-12-22-32-42-5

 

4:3-13-23-33-43-5

 

5:4-14-24-34-44-5

 

「eol=#」というオプションを追加することでコメント行をスキップすることが出来ました。

ファイル名に空白を含むファイルを扱いたい時

ここまでの知識でかなりの事が出来るのですが、このままだと「ファイル名に空白を含むものの処理」がうまくできなくて困ってしまいます。ちょっとやろうとしてみましょう。

1:c:\fortest>echohoge>"samplefile.txt"

 

2:

 

3:c:\fortest>dir

 

4:C

 

5:C0AF-1B4F

 

6:

 

7:c:\fortest

 

8:

 

9:2012/03/1600:00

 

10:2012/03/1600:00

 

11:2012/03/1522:05dir1

 

12:2012/03/1522:05dir10

 

13:2012/03/1522:05dir2

 

14:2012/03/1522:05dir3

 

15:2012/03/1522:05dir4

 

16:2012/03/1522:05dir5

 

17:2012/03/1522:05dir6

 

18:2012/03/1522:05dir7

 

19:2012/03/1522:05dir8

 

20:2012/03/1522:05dir9

 

21:2012/03/1600:007samplefile.txt

 

22:2012/03/1523:51107sample.txt

 

23:2012/03/1521:5510sample1.txt

 

24:2012/03/1521:5511sample10.txt

 

25:2012/03/1521:5510sample2.txt

 

26:2012/03/1521:5510sample3.txt

 

27:2012/03/1521:5510sample4.txt

 

28:2012/03/1521:5510sample5.txt

 

29:2012/03/1521:5510sample6.txt

 

30:2012/03/1521:5510sample7.txt

 

31:2012/03/1521:5510sample8.txt

 

32:2012/03/1521:5510sample9.txt

 

33:12215

 

34:12142,817,693,696

 

1:c:\fortest>for/F%iIN(samplefile.txt)DO@echo%i

 

2:sample

 

3:

 

4:c:\fortest>for/F%iIN("samplefile.txt")DO@echo%i

 

5:sample

 

6:

 

7:c:\fortest>for/F%iIN'samplefile.txt')DO@echo%i

 

8:'sample'

 

9:

 

うーん。うまくいきません。こういう時のためにusebackqオプションがあります。このオプションを有効にすると”(ダブルクォート), ‘(シングルクォート), `(バッククォート)の扱いが変わります。

1:c:\fortest>for/F"usebackq"%iIN("samplefile.txt")DO@echo%i

 

2:hoge

 

1:c:\fortest>for/F"usebackq"%iIN'ipconfig')DO@echo%i

 

2:ipconfig

 

3:

 

4:c:\fortest>for/F"usebackq"%iIN(`ipconfig`)DO@echo%i

 

5:Windows

 

6:Wireless

 

7:

 

8:

 

9:IPv4

 

10:

 

11:

 

12:

 

13:.

 

14:

 

15:Tunnel

 

16:.

 

17:

 

18:Tunnel

 

19:.

 

20:

 

21:Tunnel

 

22:

 

23:IPv6

 

24:

 

25:

 

26:Tunnel

 

27:.

 

28:

 

29:Tunnel

 

30:.

 

31:

 

このように、usebackqオプションを有効にすると、ダブルクォートは文字列ではなくてファイル名として扱われます。シングルクオートはコマンドではなく文字列になり、バッククォートがコマンドになります。

置換

変数を置換出来る機能も見ておきましょう。置換というか表現の変更といった方が近いかもしれません。

1:c:\fortest>for/F%iIN(""test"")DO@echo%i

 

2:"test"

 

3:

 

4:c:\fortest>for/F%iIN(""test"")DO@echo%~i

 

5:test

 

変数名の前に~をつけると引用句(“)が削除されます。

1:c:\fortest>for%iIN.txt)DO@echo%i

 

2:samplefile.txt

 

3:sample.txt

 

4:sample1.txt

 

5:sample10.txt

 

6:sample2.txt

 

7:sample3.txt

 

8:sample4.txt

 

9:sample5.txt

 

10:sample6.txt

 

11:sample7.txt

 

12:sample8.txt

 

13:sample9.txt

 

14:

 

15:c:\fortest>for%iIN.txt)DO@echo%~fi

 

16:c:\fortest\samplefile.txt

 

17:c:\fortest\sample.txt

 

18:c:\fortest\sample1.txt

 

19:c:\fortest\sample10.txt

 

20:c:\fortest\sample2.txt

 

21:c:\fortest\sample3.txt

 

22:c:\fortest\sample4.txt

 

23:c:\fortest\sample5.txt

 

24:c:\fortest\sample6.txt

 

25:c:\fortest\sample7.txt

 

26:c:\fortest\sample8.txt

 

27:c:\fortest\sample9.txt

 

変数名の前に~fをつけると絶対パスで表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~di

 

2:c:

 

3:c:

 

4:c:

 

5:c:

 

6:c:

 

7:c:

 

8:c:

 

9:c:

 

10:c:

 

11:c:

 

12:c:

 

13:c:

 

変数名の前に~dをつけるとドライブ名のみ表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~pi

 

2:\fortest\

 

3:\fortest\

 

4:\fortest\

 

5:\fortest\

 

6:\fortest\

 

7:\fortest\

 

8:\fortest\

 

9:\fortest\

 

10:\fortest\

 

11:\fortest\

 

12:\fortest\

 

13:\fortest\

 

変数名の前に~pをつけるとパス名のみ表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~ni

 

2:samplefile

 

3:sample

 

4:sample1

 

5:sample10

 

6:sample2

 

7:sample3

 

8:sample4

 

9:sample5

 

10:sample6

 

11:sample7

 

12:sample8

 

13:sample9

 

変数名の前に~nをつけるとファイル名のみ表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~xi

 

2:.txt

 

3:.txt

 

4:.txt

 

5:.txt

 

6:.txt

 

7:.txt

 

8:.txt

 

9:.txt

 

10:.txt

 

11:.txt

 

12:.txt

 

13:.txt

 

変数名の前に~xをつけると拡張子のみ表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~si

 

2:c:\fortest\SAMPLE~1.TXT

 

3:c:\fortest\sample.txt

 

4:c:\fortest\sample1.txt

 

5:c:\fortest\sample10.txt

 

6:c:\fortest\sample2.txt

 

7:c:\fortest\sample3.txt

 

8:c:\fortest\sample4.txt

 

9:c:\fortest\sample5.txt

 

10:c:\fortest\sample6.txt

 

11:c:\fortest\sample7.txt

 

12:c:\fortest\sample8.txt

 

13:c:\fortest\sample9.txt

 

変数名の前に~sをつけると短い名前を表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~ai

 

2:-a------

 

3:-a------

 

4:-a------

 

5:-a------

 

6:-a------

 

7:-a------

 

8:-a------

 

9:-a------

 

10:-a------

 

11:-a------

 

12:-a------

 

13:-a------

 

変数名の前に~aをつけるとファイルの属性を表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~ti

 

2:2012/03/1600:00

 

3:2012/03/1523:51

 

4:2012/03/1521:55

 

5:2012/03/1521:55

 

6:2012/03/1521:55

 

7:2012/03/1521:55

 

8:2012/03/1521:55

 

9:2012/03/1521:55

 

10:2012/03/1521:55

 

11:2012/03/1521:55

 

12:2012/03/1521:55

 

13:2012/03/1521:55

 

変数名の前に~tをつけると日付/時刻を表示します。

1:c:\fortest>for%iIN.txt)DO@echo%~zi

 

2:7

 

3:107

 

4:10

 

5:11

 

6:10

 

7:10

 

8:10

 

9:10

 

10:10

 

11:10

 

12:10

 

13:10

 

変数名の前に~zをつけるとファイルのサイズを表示します。

1:c:\fortest>for%iIN.txt)DOecho%~$PATH:i

 

2:

 

3:c:\fortest>echo

 

4:ECHOON>

 

1:c:\fortest>setPath=%Path%;c:\fortest

 

2:

 

3:c:\fortest>for%iIN.txt)DOecho%~$PATH:i

 

4:

 

5:c:\fortest>echoc:\fortest\samplefile.txt

 

6:c:\fortest\samplefile.txt

 

上記の例はかなりわかりにくいですが、環境変数PATHの中に記述されているディレクトリを探し、そこに検索結果のファイルやディレクトリが合致すれば表示される、そうでなければ空になる、という動きをします。PATHに含まれているファイル、ディレクトリなのかどうかの判定に使えると思います。

バッチファイルに記述する場合の注意

ここまでforを見てきましたが全て「コマンドプロンプト上で実行する際の記述」であることに注意してください。ヘルプにも以下の記載があります。

バッチ プログラムで FOR コマンドを使用するときは、%変数の代わりに、%%変数を使用してください。 「コマンドプロンプトで動いたものをそのままバッチファイルに貼りつけてはいけない」ということです。

具体的には以下の例であれば

1:c:\fortest>for%iIN.txt)DO@echo%i

 

2:samplefile.txt

 

3:sample.txt

 

4:sample1.txt

 

5:sample10.txt

 

6:sample2.txt

 

7:sample3.txt

 

8:sample4.txt

 

9:sample5.txt

 

10:sample6.txt

 

11:sample7.txt

 

12:sample8.txt

 

13:sample9.txt

 

バッチファイルには以下の用に記述する必要があります。

1:for%%iIN.txt)DO@echo%%i

 

注意して下さい。

 

forの可能性

さて、ここまでforコマンドでできることを見てきました。「かなりの事ができる」ということがお分かりいただけたかと思います。「もういやだ」という人も多いかとは思いますが…。でも、バッチファイルを作るしか無いのであれば仕方が無いです……。

随分このエントリも長くなってしまいました。forを駆使した使える実例に関してはまた別のエントリで紹介したいと思います。