Programming Field

環境変数の使い方 - DOS/コマンドプロンプト コマンド一覧

このページでは、バッチプログラムなどを記述する際に必須とも言える内容である「環境変数」(かんきょうへんすう)について記述しています。

環境変数について

環境変数は、「環境」と呼ばれる、様々なプログラムが動作する空間上に存在するもの(変数)です。一つの環境変数は「名前」と「値」のペアで構成されており、環境には複数の環境変数が存在しています。

環境は、原則として実行されるプログラムごとに(独立して)作成されます。また通常は、あるプログラムが別のプログラムを実行すると環境が複製され、実行されたプログラムはその新しい環境に属すことになります。したがって、プログラム内で環境変数の値を変更しても、そのプログラムが終了するとその変更は破棄されます。例えばコマンドプロンプト内で環境変数を変更した場合、その変更はコマンドプロンプト及びそこから実行されたプログラムにのみ影響があり、Exitコマンドなどで終了するとその変更は無かったものになります。

実行するコマンドやプログラムによっては、特定の環境変数を読み込み、その値を利用してプログラムの動作を決定することがあります。例として、Copyコマンドは「COPYCMD」という環境変数を読み込み、その値をコマンドの引数として処理します。そのため、バッチプログラムでは「特定の環境変数の値をセットしてから特定のプログラムを起動する」という内容を記述することができます(一部のバッチプログラムはこれを目的として作成されています)。

コマンドやバッチプログラムにおける環境変数の使い方

環境変数は、変数名を2つの「%」で挟むことでその値を使用することができます。例えば以下のように使います。

echo %MYVAR%
%SystemRoot%\system32\notepad.exe hoge.txt

また、変数に値を設定する場合はSetコマンドを使用します。

set MyVar=Hello

変数名は最初に設定したときにそのときの大文字・小文字が使用されますが、大文字・小文字は区別されずに使用・管理されます。

なお、「%」を用いて環境変数の値を使用する場合、環境変数の値はコマンドを実行する前に展開されます。具体的には後述する例をご覧ください。

[Windows NT系] SetlocalEndlocalを利用することで、一時的に「環境」を複製してその環境下でコマンドを実行することができます。ただし、この間は元の環境における環境変数が変更できなくなることに注意してください(Endlocalまたはプログラム実行終了時に破棄されます)。

[Windows NT系] [拡張構文] Setlocalの「enabledelayedexpansion」オプションを利用すると、「%」の代わりに「!」を用いることができるようになります。これは、環境変数を展開するタイミングをコマンドの「塊」を実行するタイミングではなく「塊」の中にあるそれぞれのコマンドを実行するタイミングに遅らせたいときに使用します。具体的には後述の例および「!」のページをご覧ください。

よく使われる環境変数

[Windows NT系] [拡張構文] コマンドプロンプトが用意する特殊な環境変数については「%」のページをご覧ください。

TEMP
MS-DOS以降
C:\Temp、%USERPROFILE%\AppData\Local\Temp など
「一時ディレクトリ」の場所を指します。一時ディレクトリは、プログラムの処理を行う際に一時的にファイルを生成するための親ディレクトリを表し、一般的にはこの中に残っているファイルは(使用中でない限り)いつでも削除可能です。
なおMS-DOSでは手動で設定する必要がありますが、一部プログラムはこの環境変数を使用しています。
TMP
Windows 95以降
C:\Temp、%USERPROFILE%\AppData\Local\Temp など
通常は「TEMP」と同じ値が入ります(Windows上ではTEMPよりもTMPの値が優先されます)。
PROMPT
MS-DOS以降
$p$g など
「プロンプト」(ユーザー入力待ち)を表示する際に画面に出力するパターンを指定します(大文字・小文字は問われません)。詳しくはPromptをご覧ください。
PATH
MS-DOS以降
C:\DOS、C:\Windows\system32;C:\Windows など
ディレクトリ名を省略してプログラム/コマンドを実行する際に検索されるディレクトリのリストを指定します。詳しくはPathをご覧ください。
COMSPEC
MS-DOS以降
C:\DOS\COMMAND.COMC:\Windows\system32\cmd.exe など
コマンドインタープリターのパスを指定します。MS-DOSでは実行したプログラムの動作によってコマンドインタープリターを読み込み直すことがあり、その場合この環境変数の値が使用されます。
Windowsではこの値はシステムによって設定されますが、変更することもできます。
windir
Windows 95以降
C:\Windows など
「WINDOWSディレクトリ」の絶対パスが入ります。この値はWindowsによって設定されますが、その値の実体が存在するレジストリを直接変更するとシステムの動作に悪影響が出る可能性があります。
OS
Windows NT系
Windows_NT
「Windows NT系列」(XPやVista以降も含む)であることを示す「Windows_NT」という文字列が入ります。Windows 95/98/Meではこの変数が存在しないため、この変数の値をチェックすることでWindowsのバージョンの切り分けをある程度行うことができます。
SystemDrive
Windows NT系
C: など
「システムが存在するドライブ」が入ります。この値はWindowsのインストール時に決定されます(インストール先によっては「C:」が入るとは限りません)。この値は末尾が「\」で終わりません。
SystemRoot
Windows NT系
C:\WINNT、C:\Windows など
「システムのルートディレクトリ」の絶対パスが入ります。この値はWindowsのインストール時に決定され、多くのプログラムやレジストリの設定内で使用されます(例として「%SystemRoot%\system32」はシステムのプログラムやDLLなどが入るディレクトリを指します)。
PATHEXT
Windows NT系
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC など
プログラムを実行する際に拡張子が無い名前が指定されたとき、実際のファイル名を検索するときに使用される拡張子が入ります(セミコロンが区切り文字として使用され、複数指定することができます)。例えばPATHEXTが「.COM;.EXE;.BAT」となっていた場合に「Test」というコマンドが実行された場合は、「Test.com」「Test.exe」「Test.bat」の順でファイルが存在するかどうかを確認し、最初に存在したファイルを実行します。この環境変数はWindowsの設定などで変更することもできますが、システムによって使用される変数のため、むやみに変更すると正しくプログラム/コマンドを実行できなくなることがあります。
HOMEDRIVE
Windows NT系
C: など
ユーザーのホームディレクトリが作成されるドライブが入ります。この値はWindowsのインストール時に決定されます(インストール先によっては「C:」が入るとは限りません)。この値は末尾が「\」で終わりません。
HOMEPATH
Windows NT系
\Users\<user-name>、\Documents and Settings\<user-name> など
現在ログオンしているユーザーの「ホームディレクトリ」の、ドライブ名を除く絶対パスが入ります。このディレクトリの中にユーザーごとの設定やドキュメントファイルなどが保存されます。
なお、「マイドキュメント」は「%HOMEDRIVE%%HOMEPATH%\Documents」とは限らないのでご注意ください。「マイドキュメント」のパスは環境変数上には現れません。
NUMBER_OF_PROCESSORS, PROCESSOR_ARCHITECTURE, PROCESSOR_IDENTIFIER, PROCESSOR_LEVEL, PROCESSOR_REVISION
Windows NT系
それぞれプロセッサーの数や種類などを示す値が入ります。システムによって決定されます。
COMPUTERNAME
Windows NT系
システムのコンピューター名が入ります。
USERNAME
Windows NT系
SYSTEM、Administrator など
現在プログラムを実行しているユーザーの名前が入ります。「サービス」など、システムが直接実行している場合は「SYSTEM」が入ります。
USERDOMAIN
Windows NT系
現在プログラムを実行しているユーザーのドメイン名が入ります。「サービス」など、システムが直接実行している場合は存在しない場合があります。

注意点

環境変数が展開されるタイミングは、原則としてコマンドの実行前です。そのため、環境変数に含まれる内容によっては、正しくコマンドを実行できなくなる場合があります。例えば、

if not %OS%==Windows_NT goto NotSupported

は、「OS」の値が存在しないとき以下のように実行されます。

if not ==Windows_NT goto NotSupported

この構文は、MS-DOSやWindows 95/98/Meでは無効な構文となります。

これを回避するには、

if not "%OS%"=="Windows_NT" goto NotSupported

とすることで、

if not ""=="Windows_NT" goto NotSupported

と展開されるため、MS-DOSやWindows 95/98/Meでも実行できるようになります。

[Windows NT系] Windows NT系(コマンドプロンプト)では、Setを用いて環境変数に設定することのできる文字が増えているため、環境変数の値に一層注意する必要があります。例えば、

set MYVAR1=^<hoge^>

と実行すると「MYVAR1」に「<hoge>」という値が入るため、これを

echo %MYVAR1%

のように利用してしまうと、

echo <hoge>

となり、リダイレクションの「<」「>」を含むコマンドと解釈されてしまいます。

サンプル1

%COMSPEC% /k myprog1.bat

環境変数「COMSPEC」にプログラム/コマンドが入っているものと仮定し、そのプログラム/コマンドを引数「/k myprog1.bat」で実行します。

なお、COMSPECは通常Command.com(MS-DOS, Windows 95/98/Me)またはCmd.exe(Windows NT系)のパスが指定されています。「/k」オプションについてはそれぞれのページをご覧ください。

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

set TEMP_FILE=%TEMP%\tempdata.txt
echo AppVersion: %HOGE_VERSION%>"%TEMP_FILE%"
echo Language: %HOGE_LANGUAGE%>>"%TEMP_FILE%"
piyo.exe "%TEMP_FILE%"
del "%TEMP_FILE%"

環境変数「TEMP」にディレクトリが入っているものと仮定し、その中のファイル「tempdata.txt」を指すパスを「TEMP_FILE」に設定して、Echoコマンドと「>」「>>」を用いてそのファイルにデータを書き込みます。その後「piyo.exe」の引数にファイルのパス(「TEMP_FILE」の中身)を指定し、実行後にファイルを削除しています。

サンプル3

set INPUT_DIR=.\Files
set OUTPUT_DIR=.\Output
trans.exe

環境変数「INPUT_DIR」と「OUTPUT_DIR」を設定して「trans.exe」を実行します。trans.exe は現在の環境がコピーされた新しい環境の中で実行されるため、ここで設定した環境変数の値を trans.exe の中で使用することができます。したがって、プログラムが使う環境変数を事前に設定しておくことでプログラムの動作を制御することができます。

サンプル4

set /p MY_OPTION="Enter the option:"
foo.exe /option:"%MY_OPTION%"

[Windows NT系] [拡張構文] Setコマンドを用いて環境変数「MY_OPTION」の値を任意に入力してもらい、その値をfoo.exeの引数として渡しています。「MY_OPTION」の値がどんな値になるか分からないため、「" "」で括ることで誤作動を防止しています。(※ ただし、この場合「foo.exe」が「" "」およびその中身を正しく解釈する必要があります。)

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

setlocal enabledelayedexpansion
nmake || exit /b !errorlevel!
bar

[Windows NT系] [拡張構文] Setlocal「!」を使用可能にした後「nmake」コマンドを実行しています。「nmake」コマンドが失敗した(終了コード0以外を返した)場合、Exitコマンドでバッチファイルを終了させる処理を行っています(「||」も参照)が、その終了コードを使用する際に

nmake || exit /b %errorlevel%

のように「%errorlevel%」を使用すると、「||」でつないでるコマンドは一連の「塊」であるため、「nmake」を実行する前にこのコマンドの「塊」に含まれる環境変数がすべて展開されて

nmake || exit /b 0

となり、「nmake」が失敗しても正しい終了コードを返せなくなってしまいます。