Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
S-JIS[2006-07-07/2013-03-05] 変更履歴

MS-DOSバッチファイル

DOSのコマンドをファイルに書いておき、バッチとして実行することが出来る。(UNIXのシェルスクリプトに相当)


実行方法

バッチファイルの拡張子をbatにしておく。

このファイルがある場所を環境変数PATHに追加しておくか、ファイルのある場所まで移動して、
コマンドラインからファイル名を入力するか、拡張子を除いた部分を入力することによって バッチを実行する。
またはフルパスでファイル名を入力する。
ディレクトリやファイル名にスペースが入っている場合は、全体をダブルクォーテーションでくくらないと、スペースの所で区切られてしまう。(コマンド用のファイル名にスペースを入れることはあまり無いだろうが…)

C:\temp>test.bat
C:\temp>test
C:\>C:\temp\test.bat
C:\>"C:\temp\test.bat"	…ダブルクォーテーションでくくっても可

引数の注意点

バッチファイル名の後ろにスペース区切りで引数を並べることが出来る。[2013-03-05]

C:\temp> test.bat aaa bbb ccc

ところが、引数の区切り文字はスペースだけではない。
等号「=」やセミコロン「;」・カンマ「,」も区切り文字として認識される。すなわち、等号をデータとして渡すことが出来ない。
ダブルクォーテーションで囲めば渡すことは出来るが、受け取った側で囲み文字を除去する必要がある。

> type test.bat
@echo args: %1 %2 %3 %4

> test.bat a=b,c;d
args: a b c d

> test.bat "a=a" "b,b" "c;c" d
args: "a=a" "b,b" "c;c" d

参考: Microsoftのセミコロン、等号 (=)、バッチ ファイルの引数として


バッチファイルの書き方

普通にコマンドプロンプトからコマンドを打つように、ファイルの中にコマンドを書いていくだけ。(通常のテキストファイルと同様)
ただし、コマンドプロンプトから直接コマンドを実行するのとは多少異なる部分もある。


@echo off

コマンドが実行時にいちいち表示されるのは邪魔なので、
定石としては、ファイルの先頭に以下のコマンドを書いておくことが多い。

@echo off

デフォルトでは、バッチファイルの実行時には コマンドを表示してからそのコマンドを実行する(UNIXのsh -xのようなもの)。
「echo off」を実行しておけば、それ以降はコマンドを表示しなくなる。
しかし「echo off」だけだと、その文(echo offそのもの)だけは表示されてしまう。そこで「@」を付けて、その文も表示しないようにしている。完璧。
(だから、「echo off」をせずに、全てのコマンドに「@」を付けてもいいわけだが)
(ちなみに、バッチでなく、コマンドプロンプトから直接「echo off」をすると面白い事に(爆) 分かると思うけど、戻すには「echo on」ね)


バッチの中から別のバッチを実行する方法

バッチファイルの中から別のバッチを呼び出すことも出来る。[2007-03-07]

バッチの中で直接バッチファイル名を書くと、そのバッチへ制御が移る。すなわち、呼び出したバッチが終了しても呼出元のバッチには復帰しない

他のバッチへ移る.bat:

echo "start"
test.bat
echo "ここへは戻って来ない!"

制御を戻したい場合には、CALL命令を使う。(戻り値を返すには、「exit /b」を使用する)

他のバッチを呼び出す.bat:

echo "start"
call test.bat
echo "戻ってきた" %ERRORLEVEL%
pause

exit /b」でなく「exit」で終了するバッチファイルを呼び出すと、exitが呼ばれた時点でコマンドプロンプトが終了してしまう。
この場合はcmd /cを使ってバッチを呼び出してやると、「exit 戻り値」で設定した戻り値が取得できる。

exitで終了するバッチを呼び出す.bat:

echo "start"
cmd /c test.bat
echo "返ってきた♪" %ERRORLEVEL%
pause

コマンドプロンプトのタイトルの変更方法

WindowsXPでバッチファイルをダブルクリックして実行した場合、コマンドプロンプトのウィンドウが起動して、そこで実行される。[2009-11-14]
このとき、ウィンドウのタイトルは「C:\WINDOWS\system32\cmd.exe」となる。たくさんバッチファイルを実行すると、区別が付かない…。

バッチファイルの中でtitleコマンドを使うと、ウィンドウのタイトルが設定できる。

title ウィンドウのタイトル

バッチファイルの場所の取得方法

バッチファイルの在る場所からの相対パスを指定したいことがある。[2009-11-14]

例えば環境変数CDはカレントディレクトリー(実行時の作業ディレクトリー)であって、バッチファイルの場所ではない。

バッチファイルの場所は、特殊な変数%0」を利用することで取得することが出来る。

set BATDIR=%~dp0

%0はバッチファイルそのものを表し、~dはそのドライブ、~pはそのパスを表す。(~dpでドライブ+パス)

「C:\temp\test.bat」内で上記のコマンドを実行すると、環境変数BATDIRは「C:\temp\」となる。
末尾に「\」が付いているので、「%BATDIR%\zzz.txt」とすると、
実際の展開時は「C:\temp\\zzz.txt」となり、「\」が2つ付いてしまう。悪影響があるどうかは、そのパスを受け取るコマンド次第。
「%BATDIR%zzz.txt」とすれば問題無いわけだが、一見すると違和感がある。

UNIXでシェルスクリプトファイルの場所を取得する方法


変数の使い方

バッチファイル内では環境変数がそのまま使える他、バッチの実行時引数が(読み込み専用の)変数として使える。

環境変数の使い方はsetコマンドを参照。

特殊な変数

環境変数の他に、バッチの実行中に自動的に値が設定される変数と、for文で使用する独自の変数がある。

引数を扱う変数にはバッチの実行時引数が入っているが、サブルーチンが呼び出された場合にはそのサブルーチンの引数が入る。
UNIXとは異なり、引数を指定する際にダブルクォーテーションが付いていたら、付いたまま変数に入ってくる。

変数 内容 UNIX相当
%ERRORLEVEL% 直前に実行されたコマンド(や関数)の戻り値 $?
%0 実行コマンド名 $0
%1 %2 … %9 実行時引数(個別) $1 $2 …
%* 全引数 $* $@

shiftコマンドで、個別の引数が1つ左へずれる。UNIXのshiftに相当。
すなわち、%0には%1の値が入り、%1には%2の値が入り…、%9には%10相当の値が入る。

%0も変わってしまうのと、%*は変わらない点がUNIXと違う
%0を変えたくない場合はオプションを付けて「shift /1」とする。これで%1以降だけが変わるようになる。


引数の変数やfor文の変数には、加工して展開する機能がある。
詳細は「help call」「call /?」「help for」「for /?」を参照。

加工の指定(修飾子)は1文字で表すが、複数の文字を組み合わせて指定することで、複合した編集が出来る(例:dpnx)。[2009-11-14]

以下の例では、カレントディレクトリが「c:\temp」、%1が「"abc"」(abcというファイルは存在しない)、%2が「zzz.txt」(存在する)とする。

指定方法 説明
%~変数 %変数の値がダブルクォーテーションでくくられているとき、ダブルクォーテーションを削除したものになる。 echo %~1
→「abc」が表示される
%~f変数 %変数の値をフルパス(絶対パス)に変換したものになる。
..」等の相対パス指定が入っていた場合、それらが取り除かれた正しい状態になる。
echo %~f1
→「C:\temp\abc」が表示される
%~d変数 %変数の値をフルパスで扱う際のドライブ名になる。 echo %~d1
→「C:」が表示される
%~p変数 %変数の値をフルパスで扱う際のパス名になる。 echo %~p1
→「\temp\」が表示される
%~dp変数 %変数の値をフルパスで扱う際のドライブ+パス名になる。[2009-11-14] echo %~dp1
→「C:\temp\」が表示される
%~n変数 %変数の値のファイル名部分(拡張子なし)になる。 echo %~n2
→「zzz」が表示される
%~x変数 %変数の値の拡張子(ピリオド付き)になる。 echo %~x2
→「.txt」が表示される
%~nx変数 %変数の値のファイル名(拡張子あり)になる。 echo %~nx2
→「zzz.txt」が表示される
%~s変数
%~fs変数
%変数の値を短縮形(dir /xと同等)に変換したものになる。[2008-08-02]
はずなのだが、なんだかバグがある(正しい形にならない事がある)。(WindowsXP SP3)
 
%~a変数 %変数の値のファイルが存在するとき、そのファイルの属性になる。 echo %~a2
→「--a------」が表示される
%~t変数 %変数の値のファイルが存在するとき、そのファイルの更新日時になる。 echo %~t2
→「2006/07/07 23:59」が表示される
%~z変数 %変数の値のファイルが存在するとき、そのファイルのサイズになる。 echo %~z2
→「5」が表示される
%~$環境変数:変数 %変数の値のファイルが 環境変数(例えばPATHやCLASSPATH)で列挙されているディレクトリに存在するかどうか調べ、存在していればそのファイル(フルパス)になる。
「~」と「$」の間には前述のfd等の指定を入れることが出来、それぞれの指定に従って変換される。
この機能を使うと、UNIXのwhichもどきが作れる。
%3が「help.exe」のとき、
echo %~dpnx$PATH:3
→「C:\WINDOWS\system32\help.exe」が表示される

環境変数の加工方法


バッチの構文

if

if 条件 コマンド if 条件 (コマンド) else コマンド

if 条件 (コマンド) else (コマンド)
if 条件 (
コマンド

) else (
コマンド

)

UNIXのifに相当。
条件が真のとき、直後のコマンドを実行する。
複数のコマンドを実行したい場合は、コマンド群を「( )」(丸括弧)でくくる。

条件が偽のとき、elseがあれば その直後のコマンドを実行する。
「if」と「else」は同じ行に無ければならない。具体的には、「if」と最初の「(」が同じ行にあり、「)」と「else」が同じ行にあればよい。
elseの直後には空白が必要。

条件には、以下の比較演算が使える。(大文字でも小文字でもよい)

比較演算子
== EQU NEQ 比較
LSS LEQ
GTR GEQ
大小比較
単項演算子
NOT 否定 if not "%1" == "" echo 引数があります
DEFINED 環境変数が存在するとき、真 if defined TMP echo 有る
EXIST ファイル(やディレクトリ)が存在するとき、真
ファイル名をダブルクォーテーションでくくることも出来るが、末尾のスペースは無視される模様。
if exist zzz.txt echo 在る
ERRORLEVEL %ERRORLEVEL%が値以上
なぜこんな演算子がわざわざあるかについては、注意点を参照。
if errorlevel 1 echo エラー

ANDやORに当たるものは無いので、複雑な演算は出来ない。

両方の項が数字だけで構成されていれば、数値として比較される。
それ以外は文字列として比較される。
例えば「"1"」は数値ではない(ダブルクォーテーションは数字じゃない)ので、「1」とは異なる。

また、「/i」オプションを付けると、大文字小文字を無視して比較する。

if /i %1 equ abc (echo 一致!) else (echo 不一致)


→then部・else部で環境変数を使う場合の注意


for

for /L %変数 in (開始,増分,終了) do コマンド for /L %変数 in (開始,増分,終了) do (
コマンド

)

変数が開始〜終了まで変化し、その回数分do以降が実行される。

>for /L %i in (1,1,10) do echo %i

→1〜10が表示される。「(10,1,10)」なら10のみ、「(11,1,10)」なら一回も実行されない。


for文の変数は他の構文と比べると異色で、変数名は英字1文字。大文字と小文字は区別されるので別の変数となる。
コマンドプロンプトから直接for文を使う場合は変数は「%i」等でよいが、バッチ内に記述する場合は「%%i」のように「%」を2つ書かなければならない。

変数(%i)の加工
→do部で環境変数を使う場合の注意


for each

for %変数 in (複数の値) do コマンド

UNIXのforに相当。
in以降の複数の値について、1個ずつ処理を行う。区切り文字にはスペース・カンマ・セミコロンが使える。

「@」を使って実行時のコマンド表示を行わないようにしたい場合、以下のように2箇所に付ける必要がある。[2009-11-14]

@for 〜 do @コマンド

直接列挙

>for %i in (aa bb cc) do echo %i
>for %i in (aa,bb,cc) do echo %i
>for %i in (aa;bb;cc) do echo %i

「aa」「bb」「cc」が表示される。

値の中に「)」が含まれていると当然のことながらそこで列挙の終了とみなされ、本来の「)」がエラーになるので注意。

>for %i in (aa bb) cc) do @echo %i
cc) の使い方が誤っています。
>for %i in (aa bb^) cc) do @echo %i
aa
bb)
cc

変数の展開

>for %i in (%CLASSPATH%) do @echo %i

環境変数CLASSPATH(セミコロン区切りでディレクトリが並んでいる)の中が1つずつ表示される。

for %%i in (%*) do @echo %%i	バッチ内で使う例

バッチの引数が1つずつ表示される。

ワイルドカードの展開

>for %i in (C:\*) do @echo %i

>for %i in (C:\lib1\*.jar C:\lib2\*.jar) do @echo %i

ワイルドカードが入っていると、そのディレクトリ(パスが指定されていない場合はカレントディレクトリ)のファイル名の一覧になる。(ファイルのみで、ディレクトリは入らない)
スペースやセミコロン「;」で(ワイルドカード入りのパスでも)複数のパスを区切ることも出来る。[2009-02-20]

>for /d %i in (C:\*) do @echo %i

「/d」オプションを付けると、ディレクトリのみが対象になる。

>for /r %i in (*.txt) do @echo %i

「/r」オプションを付けると、サブディレクトリも再帰的に探索対象となる。

ファイルの内容

>for /f "オプション" %i in (ファイル名) do @echo %i	…ファイルの内容(各行)でループ
>for /f "オプション" %i in ("文字列")   do @echo %i	…文字列を処理
>for /f "オプション" %i in ('コマンド') do @echo %i	…コマンドの実行結果(標準出力の各行)でループ

指定された対象の行ごとにループする。空行は無視される。
デフォルトでは、変数(上記の例では%i)には行の先頭の1語が入る。

オプションはダブルクォーテーションでくくって、以下のものを指定する。(スペース区切りで複数指定可能)

skip=行数 ファイルのその行数分だけスキップする。
eol=字 その文字で始まる行は、コメント行として無視する。
>for /f "eol=;" %i in (";コメント") do @echo %i
tokens=番号 その番号個目のカラムを変数に入れる。(デフォルトでは1)
>for /f "tokens=2" %i in ("a b c") do @echo %i
b

番号をカンマ区切りで列挙すると、そのカラムが変数に入れられる。
変数は最初に指定されていたものから順番に、暗黙に増える。(指定したのがiならj,k,l,…、aならb,c,d,…)

>for /f "tokens=1,3" %i in ("a b c") do @echo %i %j
a c

ハイフンでカラムの範囲を指定することも出来る。

>for /f "tokens=2-4" %i in ("a b c d e") do @echo %i %j %k
b c d

番号の代わりに「*」を指定すると、行の残りの部分全てになる。

>for /f "tokens=1,*" %i in ("a b c d e") do @echo %i -- %j
a -- b c d e
>for /f "tokens=*" %i in (test.txt) do @echo %i	…行を全部表示
delims=文字 デリミター(区切り文字)を指定する。(デフォルトではスペース)
>for /f "delims=,; tokens=1-3" %i in ("abc;def,ghi") do @echo %i %j %k
abc def ghi
usebackq ファイル名指定の引用符の意味を変える。
デフォルトでは 引用符を何も付けないとファイル名指定だが、空白が入っているファイル名には対応していない。
このオプションを付けることにより、ダブルクォーテーションがファイル名指定になる。(したがって空白が入っているファイル名を指定できるようになる)
>for /f "usebackq" %i in ("ファイル名") do @echo %i	…ファイルの内容でループ
>for /f "usebackq" %i in ('文字列')     do @echo %i	…文字列を処理
>for /f "usebackq" %i in (`コマンド`)   do @echo %i	…コマンドの実行結果でループ

ファイルの内容を環境変数に入れる例

forで「/f」を付けるとファイルを読み込めるので、forの本体で環境変数に変数の値をセットすれば、ファイルの内容を環境変数にセットすることが出来る。[2012-07-14]

↓以下の例は、バッチファイルに記述する想定(つまり、変数の指定が「%%」になっている)

@echo off
for /f %%i in (test.txt) do set ZZZ=%%i
echo ZZZ=%ZZZ%

ファイルの内容が複数行ある場合は、全部読み込んで全ての行に対して同じ処理を行うので、最終行の内容が環境変数に入ることになる。

スペース区切りで区切られている単語の4番目だけ取得したいような場合、トークンを指定する。

@echo off
type test2.txt

for /f "tokens=4" %%i in (test2.txt) do set ZZZ=%%i
echo ZZZ=%ZZZ%
this is a pen
ZZZ=pen

ファイルの内容が複数行に亘る場合は、必要な行までスキップして、途中でforを抜けるのがいいだろう。

@echo off
type test3.txt

for /f "skip=2 tokens=4" %%i in (test3.txt) do (
  set ZZZ=%%i
  goto END_LOOP1
)
:END_LOOP1

echo ZZZ=%ZZZ%
this is a pen
this is a apple
this is a orange
this is a foo
ZZZ=orange

コマンドを実行した結果を環境変数に入れる例

forで「/f」を付け、入力(コマンド)をシングルクォーテーションで囲むと、コマンドを実行した結果(標準出力の内容)を取得することが出来る。[2012-07-14]
(コマンドの戻り値はERRORLEVELで取得する)

↓以下の例は、バッチファイルに記述する想定(つまり、変数の指定が「%%」になっている)

@echo off

for /f %%i in ('date /t') do set ZZZ=%%i

echo date=%ZZZ%
date=2012/07/14

forにデリミターとトークンを指定すると、ちょっとした加工を行うことも出来る。

@echo off

for /f "delims=/ tokens=1-3" %%i in ('date /t') do (
  set ZZZ1=%%i%%j%%k
  set ZZZ2=%%i-%%j-%%k
)

echo date=%ZZZ1%
echo date=%ZZZ2%
date=20120714
date=2012-07-14

※日付の取得に関しては、環境変数DATEを使う方法もある。どちらが楽かなぁ?^^;


goto

:ラベル
goto ラベル

MS-DOSには高度なループ構文は無いので、gotoでジャンプすることで対応する。

if %~1 == abc goto match
echo 不一致
goto :EOF

:match
echo 一致

:EOFというラベルは、暗黙に定義されている。ここへのgotoは「バッチファイルの終了へ飛ぶ 」、すなわち「バッチを終了する」ということ。
(通常のgotoではラベル名に「:」コロンは不要だが、:EOFへのgotoには必要)

なお、「exit /b」を使えば同じくバッチを終了する。こちらの方が戻り値を返せるのでいいだろう。


switch

:ラベル
goto %環境変数%

MS-DOSにはUNIXのcaseに当たるものは無いが、gotoのラベルは変数を使って動的に変えることができるので、これで代用することが出来なくはない。

set CASE=1
goto caseA_%CASE%		…CASEの値に応じて、:caseA_1:caseA_2へ飛ぶ
:caseA_1
  echo case1
  goto :caseA_end
:caseA_2
  echo case2
  goto :caseA_end
:caseA_end

このやり方だと、「その他」に当たるものが出来ないが…。
(存在しないラベルへ飛ぼうとするとエラーになるから)


サブルーチン

定義 呼び出し
:ラベル
setlocal

endlocal
exit /b 〔戻り値〕
call :ラベル
call :ラベル 引数

UNIXの関数に相当。
MS-DOSには関数は無いので、サブルーチン呼び出しで代用する。
callは本来別のバッチファイルを呼び出すものだが、ラベルを指定することで自分自身の一部を別バッチとして呼び出すことが出来る。
(ラベルなので、callの位置より後にラベルがあってもよい)
(あくまでラベルなので、gotoでそのラベルへ飛ぶことも、そのまま流れてサブルーチンの中へ入ってしまうことも出来るので注意)

引数は、バッチの実行時引数の変数で参照できる。

環境変数は呼び出し元と共有される。
setlocalを使うと、そこから先の環境変数は呼び出し元には反映されなくなる。すなわち 環境変数がローカル変数のようにして扱えるようになる。
endlocalを呼び出すと、環境変数は元の状態に戻る。endlocalを呼ばなくても、setlocalを呼び出していればバッチ終了時にendlocalの処理が暗黙に行われる)
逆に言うと、環境変数を使って呼び出し元に値を返したい場合はsetlocalは使えないので注意。

exit /b」でバッチを終了する。callで呼ばれるときは (同一バッチファイル内であっても)別バッチ扱いなので、「exit /b」ならサブルーチンだけを終了できる。

exit /b 戻り値」で戻り値を指定すると、呼び出し元の変数%ERRORLEVEL%に反映される。
(戻った後に他のコマンドを実行すると%ERRORLEVEL%の値は変わる可能性があるので注意)

test.bat:

@echo off
echo 呼び出し前:%*
call :sub aa %* bb
echo 戻り値:%ERRORLEVEL%
echo 呼び出し後:%*
exit /b

:sub
echo 呼び出された:%*
exit /b 99
>test.bat foo zzz
呼び出し前:foo zzz
呼び出された:aa foo zzz bb
戻り値:99
呼び出し後:foo zzz

バッチの戻り値

バッチの一番最後で「exit /b」を呼べばバッチが終了する。
callで呼ばれていた場合は、そのサブルーチンから抜ける)
オプションなしの「exit」は、バッチを呼び出しているコマンドプロンプト自体を終了させてしまうので要注意!)

exit /b 戻り値」として戻り値を指定すると、バッチ呼び出し元の%ERRORLEVEL%に設定される。
戻り値を指定しなかった場合は、0が返るわけではなく、%ERRORLEVEL%の値は変わらない

また、これはバッチ処理の戻り値ではないことに注意!

exit /b 戻り値」でどんな戻り値を返そうとも、バッチ処理自体は正常に終わっているので終了コードは正常(0)なのである。
バッチとしてのエラー(存在しないラベルに飛ぼうとしたとか)が発生した場合に、終了コードがエラーコードになる。

つまり、以下のような書き方には注意を要する。

>test.bat || echo fail

test.batが文法的におかしくて失敗した場合にメッセージを出したいならこれでいいが、
test.batの中で「exit /b 1」のように0以外の値を返したことによってメッセージを出したいなら、これではダメ。
後者の扱いをしたいのであれば、以下の様にすべき。

>test.bat & if errorlevel 1 echo fail	…test.batの戻り値が1以上のとき「echo fail」を実行

ちなみに、以下のような書き方は、分かりにくいが、やはりダメ

>test.bat & if %ERRORLEVEL% neq 0 echo fail
>test.bat & echo %ERRORLEVEL%

なぜなら、環境変数はその行全体の実行開始前に展開されるから。
つまり実行前に%ERRORLEVEL%の値が0だったとすると、以下のように展開されてから実行されることになる。

>test.bat & if 0 neq 0 echo fail
>test.bat & echo 0

したがって、test.batがどんな値を返して(%ERRORLEVEL%にセットされて)も、実行前の値で「&」以降が処理されるということになる。
(この為に、エラーコードチェックに関してはERRORLEVELという演算子がわざわざ用意されているわけだ。これなら値の取得自体はif文の実行時に行うわけだから。)


これはその他の環境変数を使う場面でも同様に起こり得る。特にif文for文ではよく勘違いしてやってしまう。「help for」「for /?」でもわざわざ例示されているくらいだ。

>set var=aaa
>set var=bbb & echo %var%		→「set var=bbb & echo aaa」と展開されてから実行される
aaa
>echo %var%
bbb				→「set var=bbb」が実行されなかったわけではないので、後から見ればちゃんとセットされている
set var=1
if %var% == 1 (			→「if 1 == 1 (
 set/a var=%var% + 2		   set/a var=1 + 2
 echo %var%			   echo 1
)				  )」と展開されてから実行される
set list=
for %%i in (aa bb) do @set list=%list%;%%i	→「for %i in (aa bb) do @set list=;%i」と展開されてから処理されるので、
echo %list%				 「@set list=;aa」「@set list=;bb」が実行される

なお、この問題を解消する為に遅延環境変数というものもある(遅延環境変数を有効にしないと使えないが)。

>set var=123
>set var=234 & echo 通常:%var% 遅延:!var!
通常:123 遅延:!var!

>cmd /v:on					…遅延環境変数を有効にして新しいコマンドプロンプトを起動

>set var=123
>set var=234 & echo 通常:%var% 遅延:!var!
通常:123 遅延:234

>exit						…元のコマンドプロンプトへ戻る

でも、遅延環境変数を使わなくてもサブルーチン化してやれば解決できる。[2007-06-15]

set var=1
if %var% == 1 (call :add %var%)
exit/b

:add
set/a var=%var% + 2
echo %var%
set list=
for %%i in (aa bb) do @call :add %%i
echo %list%
exit/b

:add
@set list=%list%;%1

バッチへの標準入力

バッチへのリダイレクションによるデータ入力は、バッチ内で最初に標準入力を使用するコマンドへの入力となる。[2007-10-26]
例えばechoは標準入力を使用しない為、先頭に置いておいても 標準入力のデータには影響ない。

test_more.bat:

@echo off
more

実行例:

> type aaa.txt | test_more
a1
a2

> test_more < aaa.txt
a1
a2

for文への入力に標準入力を使いたい場合は、標準入力のデータをそのまま標準出力へ出力するコマンドを利用する。
例えばfindstrを使う。(UNIXならcatが使えそうな気がするが、MS-DOSのtypeは標準入力を使えない)

test_echo.bat:

@echo off
for /f %%i in ('findstr .*') do echo %%i

実行例:

> type aaa.txt | test_echo
a1
a2

> test_echo < aaa.txt	…なぜか何も出力されない

パイプを使ったリダイレクションはちゃんと動くのに、ファイルからの入力は何故か何も出力されない…。

とりあえず、バッチ内部でパイプを経由してやると上手くいくっぽい。

test_echo2.bat:

@echo off
findstr .* | for /f %%i in ('findstr .*') do @echo %%i

実行例:

> type aaa.txt | test_echo2
a1
a2

> test_echo2 < aaa.txt
a1
a2

ただ このやり方だと、doの後ろでcallを使ってラベルに飛ぼうとすると「バッチ スクリプト外でバッチ ラベルを呼び出すことはできません。」という実行時エラーになる。
どうやら、パイプの後ろは別バッチのような扱いになるらしく、したがってラベルも別空間になるので認識できないっぽい。

なかなかベストな解決方法が見つからない…(嘆)


技術メモへ戻る / 自作バッチへ行く
メールの送信先:ひしだま