MS-DOS コマンドプロンプトとバッチファイルに関するTips。 ここで紹介するものは主にWindows XP, Windows 7にて検証したもの(他のOSでは未検証)。

環境変数

  • 値を代入するときは、「set 変数名=値」
  • 値を参照するときは、「%変数名%」
  • 値の一部分を取得するときは、「%変数:~開始位置,長さ%」

echo

echoの使い方。

echo on/off

echo on(デフォルト)の場合は、バッチファイルのコマンドがそのまま表示される。 echo offの場合は、コマンドは表示されず、結果のみが表示される。

echo 処理を始めます
echo echoを用いてメッセージを表示する
実行結果
C:\Documents and Settings\smdn\デスクトップ>echo 処理を始めます
処理を始めます

C:\Documents and Settings\smdn\デスクトップ>echo echoを用いてメッセージを
表示する

echo offにすると、バッチファイルで実行するコマンドの部分が表示されなくなる。

echo off
echo 処理を始めます
echo echoを用いてメッセージを表示する
実行結果
C:\Documents and Settings\smdn\デスクトップ>echo off
処理を始めます
echoを用いてメッセージを表示する

さらに、「@echo off」とすると、「echo off」を実行するときのコマンドも表示されなくなる。

@echo off
echo 処理を始めます
echo echoを用いてメッセージを表示する
実行結果
処理を始めます
echoを用いてメッセージを表示する

メッセージを表示する

echoに続く文字列はそのまま表示される。 環境変数は値が展開されて表示される。 「echo.」とすると空行が表示される。

echo 処理を始めます
echo 今日の日付は%DATE%です
echo.
echo OSは%OS%です
実行結果
処理を始めます
今日の日付は2007/05/19です

OSはWindows_NTです

set

setの使い方。

すべての環境変数を表示する

setコマンドをオプション無しで実行すると、現在定義されているすべての環境変数が表示される。

setコマンドですべての環境変数を表示する
C:\>set
ALLUSERSPROFILE=C:\Documents and Settings\All Users
APPDATA=C:\Documents and Settings\smdn\Application Data
CLIENTNAME=Console
CommonProgramFiles=C:\Program Files\Common Files
COMPUTERNAME=HIKARI
ComSpec=C:\WINDOWS\system32\cmd.exe
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=\Documents and Settings\smdn
LOGONSERVER=\\HIKARI
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Path=C:\PROGRA~1\JUSTSY~1\JSLIB32;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\Syst
em32\Wbem
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 8, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=0f08
ProgramFiles=C:\Program Files
PROMPT=$P$G
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\WINDOWS
TEMP=C:\DOCUME~1\SANTAM~1\LOCALS~1\Temp
TMP=C:\DOCUME~1\SANTAM~1\LOCALS~1\Temp
USERDOMAIN=HIKARI
USERNAME=smdn
USERPROFILE=C:\Documents and Settings\smdn
VS80COMNTOOLS=C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\
windir=C:\WINDOWS

環境変数を設定する

set LOGFILE=sample.log
set LOGDIR=.\logs\
echo %LOGDIR%%LOGFILE%
実行結果
.\logs\sample.log

キーボードからの入力を環境変数に代入する

/pオプションを指定してsetコマンドを実行すると、キーボードからの入力を環境変数に代入することが出来る。

echo ログファイル名は?
set /p LOGFILE=
set LOGDIR=.\logs\

echo %LOGDIR%%LOGFILE%
実行結果
ログファイル名は?
test.log
.\logs\test.log

また、次の例のようにプロンプト文字列を指定することも出来る。

set /p LOGFILE=ログファイル名は? 
set LOGDIR=.\logs\

echo %LOGDIR%%LOGFILE%
実行結果
ログファイル名は? test.log
.\logs\test.log

四則演算等の演算を行う

/aオプションを指定してsetコマンドを実行すると、四則演算等の演算を行うことが出来る。

set A=12
set B=8

set /a RESULT=%A% + %B%
echo %A% + %B% = %RESULT%

set /a RESULT=%A% - %B%
echo %A% - %B% = %RESULT%

set /a RESULT=%A% * %B%
echo %A% * %B% = %RESULT%

set /a RESULT=%A% / %B%
echo %A% / %B% = %RESULT%

set /a RESULT=%A% %% %B%
echo %A% %% %B% = %RESULT%
実行結果
12 + 8 = 20
12 - 8 = 4
12 * 8 = 96
12 / 8 = 1
12 % 8 = 4

+=演算子や-=演算子などの複合代入演算も行うことが出来る。 なお、インクリメント・デクリメント演算子は無いので、代わりに += もしくは -= を使う必要がある。

set X=3
echo %X%

set /a X+=1
echo %X%

set /a X-=1
echo %X%

set /a X*=2
echo %X%

set /a X/=3
echo %X%
実行結果
3
4
3
6
2

文字列操作

連結

2つの変数を並べることで、文字列の連結を行うことが出来る(連結するための結合演算子は無い)。

文字列の連結
set STR1=foo
set STR2=bar

set STR3=%STR1%%STR2%
echo %STR3%

set STR4=%STR3%baz
echo %STR4%
実行結果
foobar
foobarbaz

部分文字列の取得

「%変数:~開始位置,長さ%」とすることで変数の内容から部分文字列を取得できる。 長さを省略したり、負の値を指定することも出来る。 開始位置に負の値を指定すると末尾n文字目からの部分文字列、長さに負の値を指定すると末尾n文字目までの部分文字列を取得出来る。 なお文字の番号は0から始まるため、先頭の文字は0番目となる。

書式と得られる結果をまとめると次のようになる。

書式と得られる部分文字列の例 (STR=0123456789)
書式 得られる部分文字列 (下線部分)
%STR:~0% 0123456789
%STR:~0,3% 0123456789
%STR:~3% 0123456789
%STR:~3,5% 0123456789
%STR:~3,-5% 0123456789
%STR:~-5% 0123456789
%STR:~-5,2% 0123456789
%STR:~-5,-2% 0123456789
部分文字列の取得
set STR=0123456789

echo %STR:~0%
echo %STR:~0,3%
echo %STR:~3%
echo %STR:~3,5%
echo %STR:~3,-5%
echo %STR:~-5%
echo %STR:~-5,2%
echo %STR:~-5,-2%
実行結果
0123456789
012
3456789
34567
34
56789
56
567

置換

「%変数:置換前の文字列=置換後の文字列%」とすることで変数の一部分を置換した結果を得ることが出来る。 最初に一致した箇所でなく、一致する箇所全てが置換される。 置換後の文字列を省略すると空の文字列に置換されることとなり、部分文字列を削除することが出来る。

置換
set A=hogehogehoge
echo %A% : %A:o=a%

set B=test.log
echo %B% : %B:.log=.log.1%

set C=test.log.bak
echo %C% : %C:.bak=%
実行結果
hogehogehoge : hagehagehage
test.log : test.log.1
test.log.bak : test.log

キー入力があるまで処理を中断する

pauseを用いると、その部分で処理を中断し、キー入力があるまで待機する。

echo 処理を始めます
pause
echo 完了しました
実行結果
処理を始めます
続行するには何かキーを押してください . . .
完了しました

年月日を変数に代入する

システム変数%DATE%で取得できる日付の文字列を切り出して、年月日をそれぞれ別々の変数に代入する。

set YEAR=%DATE:~0,4%
set MONTH=%DATE:~5,2%
set DAY=%DATE:~8,2%

echo Date: %DATE%
echo Year: %YEAR%
echo Month: %MONTH%
echo Day: %DAY%
実行結果
Date: 2007/05/19
Year: 2007
Month: 05
Day: 19

「%変数:~開始位置,長さ%」で変数の一部分を切り出すことが出来る。 システム変数%DATE%の書式は「yyyy/mm/dd」になっているので、それぞれ一部分を切り出して別々の変数に代入することで年月日を取得できる。

時刻についても同様に取得できる。

set HOUR=%TIME:~0,2%
set MINUTE=%TIME:~3,2%
set SECOND=%TIME:~6,2%

echo Time: %TIME%
echo Hour: %HOUR%
echo Minute: %MINUTE%
echo Second: %SECOND%
実行結果
Time: 16:02:09.71
Hour: 16
Minute: 02
Second: 09

コメント

REMを使えばバッチファイル中にコメントを記述できるが、行頭にREMが並ぶのは見づらい。

REM 年月日を取得する
set YEAR=%DATE:~0,4%
set MONTH=%DATE:~5,2%
set DAY=%DATE:~8,2%

REM 年月日を表示する
echo Year: %YEAR%
echo Month: %MONTH%
echo Day: %DAY%

REMの代わりに、GOTOで使用するラベルを定義するために用いるコロン(:)を応用することで、コロン(:)で始まる行をコメント行にすることができる。

:: 年月日を取得する
set YEAR=%DATE:~0,4%
set MONTH=%DATE:~5,2%
set DAY=%DATE:~8,2%

:: 年月日を表示する
echo Year: %YEAR%
echo Month: %MONTH%
echo Day: %DAY%

コロン(:)の後ろに続く文字列がラベルとして使用されない限りは意味のない行となるため、コロン(:)で始まっていればその後ろに続く文字は何でもOK。 下記のいずれの表記も文法上エラーとはならず、また意味のない行となるため、コメント行となる。

:: コメント行
:# コメント行
:! コメント行
:% コメント行
:// コメント行

乱数を取得する

システム変数%RANDOM%を参照すると0から32767までの乱数を取得できる。

set RANDVAL=%RANDOM%

終了コードを取得する

システム変数%ERRORLEVEL%を参照すると直前に実行したコマンドの終了コードを取得できる。

:: 実行して成功となるコマンド
success.exe

echo %ERRORLEVEL%

:: 実行して失敗となるコマンド
failure.exe

echo %ERRORLEVEL%
実行結果例
0
1

ファイルの有無で処理を分岐する

if exist文を用いるとファイルが存在する場合の処理を記述できる。 さらにgoto文と組み合わせることで、ファイルが存在する場合とそうでない場合で処理を分岐させることが出来る。

set FILE=test.txt

if exist %FILE% ( goto FOUND ) else goto NOTFOUND

:FOUND
    echo ファイル%FILE%が見つかりました
    goto END

:NOTFOUND
    echo ファイル%FILE%は存在しません
    goto END

:END
    echo 終了

if not exist文を用いると、ファイルが存在しない場合の処理を記述できる。

set FILE=test.txt

if not exist %FILE% echo ファイル%FILE%は存在しません

引数

%番号とするとバッチファイルに渡されたコマンドライン引数を取得することができる。 例えば%1には1番目、%2には2番目に指定された引数が格納される。 引数に与えられたダブルクオーテーション"などはそのまま取得される。 %0にはバッチファイル自体のパス(実行時のパス)が格納される。

test.bat
@echo off

echo 0: %0
echo 1: %1
echo 2: %2
echo 3: %3
実行結果例
E:\>test.bat param1 "param 2" test.txt
0: test.bat
1: param1
2: "param 2"
3: test.txt

E:\>cd sample

E:\sample>..\test.bat param1 "param 2" test.txt
0: ..\test.bat
1: param1
2: "param 2"
3: test.txt

引数の展開と修飾子

%~(番号)のように引数番号の前に~を記述すると、引数を展開する際にダブルクオーテーション"が削除される。

test.bat
@echo off

echo %1
echo %~1
echo %2
echo %~2
実行結果例
E:\>test.bat param1 "param 2"
param1
param1
"param 2"
param 2

さらに、%~f1のように%~(修飾子)(番号)と記述すると、修飾子によって展開される結果が次のように変わる。 修飾子を指定した場合も同様にダブルクオーテーション"が削除される。

引数展開の修飾子と動作
修飾子 展開時の動作
f 引数をフルパス名に展開する
p 引数からファイル名を除いたディレクトリ部分に展開する
n 引数から拡張子を除いたファイル名に展開する
x 引数を拡張子だけに展開する
d 引数をドライブレターと:だけ(C:など)に展開する
t 引数をファイルの日時に展開する
z 引数をファイルのサイズに展開する
test.bat
@echo off

echo %1
echo %~1
echo f: %~f1
echo p: %~p1
echo n: %~n1
echo x: %~x1
echo d: %~d1
echo t: %~t1
echo z: %~z1
実行結果例
E:\>test.bat ".\sample\foo.txt"
".\sample\foo.txt"
.\sample\foo.txt
f: E:\sample\foo.txt
p: \sample\
n: foo
x: .txt
d: E:
t: 2013/12/16 00:06
z: 45

なお、これらの修飾子は組み合わせて複数指定することもできる。 そのため、次のように展開時にファイル名や拡張子を別のものに置き換えることもできる。

test.bat
@echo off

::一つ目の引数を拡張子を含むファイル名に展開
echo %~nx1

::一つ目の引数をドライブ名を含むディレクトリに展開
echo %~dp1

::一つ目の引数の拡張子を".bak"に置き換えて展開
echo %~dpn1.bak

::一つ目の引数のファイル名に"backup-"を前置して展開
echo %~dp1backup-%~nx1
実行結果例
E:\>test.bat ".\sample\foo.txt"
foo.txt
E:\sample\
E:\sample\foo.bak
E:\sample\backup-foo.txt

他のバッチファイルを呼び出す

callコマンドを用いると、他のバッチファイルを呼び出すことができる。 このとき、引数を指定することもできる。

a.bat
@echo off

set VAL1=value 1
set VAL2=value 2
call b.bat 引数1 "引数 2" %VAL1% "%VAL2%"
b.bat
echo 1: %1
echo 2: %2
echo 3: %3
echo 4: %4
echo 5: %5
echo 6: %6

echo VAL1=%VAL1%
echo VAL2=%VAL2%
実行結果
E:\>a.bat
1: 引数1
2: "引数 2"
3: value
4: 1
5: "value 2"
6:
VAL1=value 1
VAL2=value 2

環境変数は展開されてから引数として渡されるので、値に空白が含まれていると引数の区切りとみなされ、別々に渡される点に注意が必要。 環境変数に空白が含まれる場合はダブルクオーテーション"でくくることによりひとつの引数として渡すことができる。 また、callコマンドによって呼び出されたバッチファイルも同一プロセスで実行されるため、呼び先のバッチファイルから呼び元の環境変数を参照することができる。

パイプとリダイレクト

パイプ

コマンド1の標準出力をコマンド2の標準入力に接続するには次のようにする。

パイプ
コマンド1 | コマンド2

次の例では、typeコマンドによってファイルの内容を標準出力に書き出し、sortコマンドの標準入力に渡すことでsource.txtの内容をソートした状態で表示している。

パイプを使ってtypeの結果をsortコマンドに連結する
E:\>type source.txt
ab
abcd
abc
a

E:\>type source.txt | sort
a
ab
abc
abcd

次のように複数のコマンドを連結することができる。

複数のパイプ
コマンド1 | コマンド2 | コマンド3 | ...

リダイレクト

標準入力

ファイルfileの内容をコマンドcommandの標準入力に渡すには次のようにする。

標準入力のリダイレクト
command < file

標準出力

コマンドcommandが標準出力に出力する内容をファイルfileに書き込むには次のようにする。

標準出力のリダイレクト
command > file
command 1> file

STDOUTのハンドルを表す1は省略することができるので、1>は単に>と記述することができる。

標準エラー

コマンドcommandが標準エラーに出力する内容をファイルfileに書き込むには次のようにする。

標準エラーのリダイレクト
command 2> file

標準出力の場合とは異なり、STDERRのハンドルを表す2は省略することができないので、2>を単に>と記述することはできない。

標準出力・標準エラーの追記書き込み

標準出力・標準エラーをリダイレクトする場合、>>2>>と記述することでリダイレクトの際に書き込まれる内容を上書きではなくファイルに追記させることができる。

追記モードでの標準出力のリダイレクト
command >> file
追記モードでの標準エラーのリダイレクト
command 2>> file

標準入力と標準出力のリダイレクト

ファイルinput.txtの内容をコマンドの標準入力に渡し、コマンドの標準出力をファイルoutput.txtにリダイレクトする場合は次のようにする。

標準入力と標準出力のリダイレクト
command < input.txt > outout.txt

標準出力と標準エラーのリダイレクト

標準出力と標準エラーを別々のファイルにリダイレクトする場合は次のようにする。

標準出力と標準エラーを別々のファイルにリダイレクト
command > out.log 2> err.log

標準出力と標準エラーを同一のファイルにリダイレクトする場合は次のようにする。

標準出力と標準エラーを同一のファイルにリダイレクト
command > out.log 2>&1

これは次のようにすることもできる。

標準出力と標準エラーを同一のファイルにリダイレクト
(command 2>&1) > out.log

NULデバイス

UNIXの/dev/nullに相当するものとしてnulが用意されている。 例えば標準出力をnulにリダイレクトすれば出力内容はすべて破棄され、一切表示されなくなる。

NULデバイスへのリダイレクト
command > nul

文字コードの変更

chcpコマンドを用いると、使用する文字コードを変更できる。 引数で指定できる主な文字コードは次のとおり。

chcpコマンドで指定できる主な文字コード
コード 名称
932 Shift-JIS (デフォルト)
20932 EUC-JP (IS X 0208-1990 and JIS X 0212-1990)
51932 EUC-JP
65000 UTF-7
65001 UTF-8

引数を指定せずにchcpコマンドを実行すると、現在の文字コードが表示される。

実行結果1
実行結果2

なお、chcpコマンドで文字コードを変更すると、ウィンドウのサイズとフォントが代わり漢字等が正しく表示されなくなるので、次の手順であらかじめフォントを変更しておく必要がある。

  1. コマンドプロンプトのプロパティを開く
  2. 「フォント」タブで「MSゴシック」等のフォントに変更する

参考資料