Programming Field

「%」 (変数の使用) - DOS/コマンドプロンプト コマンド一覧

「%」(パーセント文字)は環境変数の値やバッチプログラムのパラメーター(引数)を使用するときに使います。

構文

%<value-name>%
%<number>
%*
%~<operators><number>
<value-name> 現在の環境で定義されている環境変数の名前を指定します。
<number> [バッチファイル] 0 から 9 の数字を指定します。この数字は、バッチファイルを実行した際に渡された引数(コマンドパラメータ)のインデックスに対応します。(Shiftが行われていない場合、「%1」が最初の引数になり、「%0」はバッチファイルのファイル名、またはCallで呼び出したラベル名になります。)
%* [Windows NT 系] [バッチファイル] バッチファイルに指定された引数全体を用いる際に利用します(「%0」分は含まれません)。引数が2文字以上のスペースで区切られている場合も、スペースも含めてそのまま入ります。また、この変数はShiftの影響を受けません。
%~<operators><number> [Windows NT 系] [拡張構文] [バッチファイル] 0から9の数字の前に「~」文字と適切な文字を指定することで引数の展開方法を変更します。詳しくは解説の引数展開の拡張をご覧ください。

解説

環境変数は、現在のDOS環境(プロンプト含む)における一種の「設定」であり、プログラムによっては環境変数の値を読み込んで処理を行うものもあります(詳しくは「環境変数について」をご覧ください)。「%」文字を使うことで、この環境変数の値を使うことができます。

なお、現在の環境で定義されている環境変数の一覧を表示したり、環境変数の値を追加・変更・削除するときは、いずれの場合もSetコマンドを使用します。

% 文字の解釈

% で囲んだ文字列がコマンド及びバッチファイル内に存在すると、システム(コマンドインタープリター)はその文字列を環境変数の名前と見なし、その環境変数の値に置き換えます。もし環境変数が定義されていない場合は空の文字列になります。

(環境変数の値を出力する例)

echo 「%TEMP%」「%UNKNOWN_VARIABLE%」
「C:\TEMP」「」

なお、バッチファイルにおいて「%」文字を出力、またはプログラムの引数として渡したい場合は「%%」と記述します。

「^」文字を使って「^%」と記述しても「%」文字を出力することは出来ません。必ず「%%」とする必要があります。
※ バッチファイルにおけるForコマンドで「%」を「%%」と記述する必要があるのはこれに関連しています。

(「%」文字を出力する例: バッチファイル test.bat)

@echo 100%% 100%
C:\MyData>test.bat
100% 100

また、% 文字は「コマンドラインの行を解析する際に最初に解析される」という仕様があるため、「&」文字や「( )」文字などで複数のコマンドをひとまとめにした場合、ひとまとめにしたコマンド一つずつ実行する前にまとめて「%」文字の処理が行われます。特にまとめたコマンド内にSetコマンドを含む場合などでは不都合な場合があるため、その場合はSetlocalコマンドで環境変数の遅延展開機能を有効にしつつ、「!」文字を使って環境変数を展開するといった対策をする必要があります。

バッチファイルの引数

バッチファイルの実行には、他のプログラムと同様に引数を指定することが出来ます、与えられた引数をバッチファイル内から用いたい場合は、「%1」「%2」... のように % 文字に数字を付けることで値を取得することができます。なお、「%0」はバッチファイルを実行した際のパス名(Callによる呼び出しの場合は「:」を含むラベル名)が入ります。

(引数を利用する例: バッチファイル test2.bat)

@echo "%0", "%1", "%2", "%3"
C:\MyData>..\test2.bat Test "parameter"
"..\test2.bat", "Test", ""parameter"", ""

※ % の後ろに指定できる数値は1桁までです。10個以上の引数を利用する場合はShiftコマンドを使用します。

環境変数展開の拡張

[Windows NT系] [拡張構文] 拡張機能が有効になっている場合、環境変数を用いる場合に、以下の構文を使うことで環境変数の展開方法を変更することができます。

記法意味
%VAR%(通常の記法)
%VAR:text1=text2%VAR内に含まれる文字列「text1」をすべて 文字列「text2」に置き換えて展開します。
%VAR:~num1,num2%VAR内のオフセットnum1の位置(num1+1文字目)からnum2文字分を取得して展開します。例えばVARが「Hello」の場合「%VAR:~1,2%」は「el」になります。
num1の前にマイナス記号が付いている場合、VAR内の最後から数えたオフセットnum1の位置(num1文字目)から最後までの文字列のうち、num2文字分を取得して展開します。例えばVARが「Hello」の場合「%VAR:~-2,2%」は「lo」になります。
num2の前にマイナス記号が付いている場合、VAR内のオフセットnum1の位置(num1+1文字目)から最後までの文字列のうち、最後のnum2文字分を除いたものを取得して展開します。例えばVARが「Hello」の場合「%VAR:~1,-1%」は「ell」になります。
%VAR:~num1%VAR内のオフセットnum1の位置(num1+1文字目)から最後までを取得して展開します。例えばVARが「Hello」の場合「%VAR:~2%」は「llo」になります。
num1の前にマイナス記号が付いている場合、VAR内の最後から数えたオフセットnum1の位置(num1文字目)から最後までを取得して展開します。例えばVARが「Hello」の場合「%VAR:~-1%」は「o」になります。

なお、記法や変数の値によって文字の位置が範囲外になる場合でもエラーにはならず、範囲外の部分は空の文字列になります(全体が範囲外の場合は全体が空の文字列になります)。例えばVARが「Hello」の場合「%VAR:~7%」は「」になります。

引数展開の拡張

[Windows NT 系] [拡張構文] バッチファイルの引数(%0~%9)を展開する際、「%」文字の直後に「~」文字を入れると引数の展開方法が変わります。「~」と数字0~9の間に以下の文字を指定するとそれぞれ以下のように展開されます。

  • 以下、「1」に当てはまる数字は「0~9」のいずれでも使用でき、「ENV」は既存の環境変数名(「PATH」など)を表します。
  • 「展開例」では、元の「%1」の値はすべて「"Text Documents\note.201311.txt"」とし、現在のディレクトリを「D:\MyDocs」とします。
  • Forコマンドにおける変数に対しても使用できますが、環境変数に対して使用することはできません。下記の展開の拡張を通常の環境変数に対して用いる場合、Callのサンプルにあるような方法やForによるテキスト解析指定(/F)を用いる必要があります。
記法意味 / 展開例
%1(拡張法を用いない場合)
"Text Documents\note.201311.txt"
%~1(「~」と数字の間に何も指定しない場合)引数内のダブルクオーテーションマーク「"」を削除して展開します。削除されるのは最初と最後の文字のみです。なお、以下の展開方法でもダブルクオーテーションマークは除去されます。
Text Documents\note.201311.txt
%~f1引数を相対パスのファイル名と見なし、絶対パスのファイル名に変換して展開します。この際指定したファイルが存在しなくても構いません。
D:\MyDocs\Text Documents\note.201311.txt
%~d1引数からドライブ文字と「:」だけを取得してその文字に展開します。引数が相対パスの場合は絶対パスに変換され、そのパスに対して適用します。
D:
%~p1引数からディレクトリ名だけを取得してその文字に展開します。ディレクトリ名にドライブ文字と「:」は含まれません。また、末尾に「\」記号が入ります。引数が相対パスの場合は絶対パスに変換され、そのパスに対して適用します。
\MyDocs\Text Documents\
%~dp1(「%~d1」と「%~p1」の組み合わせです。ディレクトリ名のみを取り出す際に用いることができます。なお、末尾は必ず「\」になります。)
D:\MyDocs\Text Documents\
%~n1引数から拡張子(とパス)を除いたファイル名だけを取得し、その文字に展開します。ファイル名のうち最も最後にある「.」とそれ以降の文字のみが除去されるため、「file.exe.config」→「file.exe」のように展開された文字列に「.」が含まれる可能性はあります。
note.201311
%~x1引数から拡張子だけを取得し、その文字に展開します。拡張子が無い場合は空の文字列になります。
.txt
%~nx1(「%~n1」と「%~x1」の組み合わせです。ファイル名のみを取り出す際に用いることができます。)
note.201311.txt
%~s1引数を相対パスのファイル名と見なし、絶対パスに変換してから「短いファイル名」に変換して展開します。このとき指定したファイルが存在しない場合は、絶対パスで表した時の存在するディレクトリの部分までが短いファイル名に変換されます。
なお、nやdなどを組み合わせている場合は「短いファイル名のうち対応する部分」が展開されます。
D:\MyDocs\TEXTDO~1\NOTE-2~1.txt
%~snx1(sをnやdなどを組み合わせている場合は「短いファイル名のうち対応する部分」が展開されます。この場合は「%~nx1」の短いファイル名版が取得できます。)
NOTE-2~1.txt
%~a1
引数を相対パスのファイル名と見なし、そのファイルの属性の文字列表現に変換して展開します。属性の文字列表現は「drahscotl」または「drahscotlvx」([Windows 8.1?以降])となり、
  • d=ディレクトリ
  • r=読み取り専用
  • a=アーカイブ可能(アーカイブ属性)
  • h=隠しファイル
  • s=システムファイル
  • c=圧縮されたコンテンツ
  • o=オフラインファイル
  • t=一時ファイル
  • l=シンボリックリンクまたはジャンクションまたは再解析ポイント(リパースポイント)
  • v=整合性ストリーム(整合性属性) ([Windows 8.1?以降])
  • x=スクラブ処理対象外 ([Windows 8.1?以降])
を表しています。それぞれの属性に当てはまらない場合は該当箇所が「-」になります。なお、ファイルが見つからない場合は空の文字列に展開されます。
※ 整合性ストリーム「v」についてはReFSファイルシステムで利用されるファイル属性です。
--a------
--a-------- [Windows 8.1?以降]
%~t1引数を相対パスのファイル名と見なし、そのファイルの日付と時刻を取得してその値に展開します。日付と時刻は日本語環境の場合「yyyy/MM/dd hh:mm」に展開されます。なお、ファイルが見つからない場合は空の文字列に展開されます。
2013/11/30 17:25
%~z1引数を相対パスのファイル名と見なし、そのファイルのサイズを取得してその値に展開します。ファイルサイズは桁区切り無しのバイト単位で取得されます。なお、ファイルが見つからない場合は空の文字列に展開されます。
34122
%~$ENV:1引数をファイル名と見なし、環境変数ENVで指定されているディレクトリリストを検索して引数で指定したファイルが最初に存在するディレクトリとそのファイルを結合した絶対パスを取得して展開されます。ENVの中身は環境変数PATHのようにセミコロン区切りで指定されている必要があります。例えば引数 %1 が「hoge.exe」、ENVの中身が「C:\foo;C:\bar;C:\piyo」となっているとき、「hoge.exe」が「C:\bar」に存在する場合「%~$ENV:1」は「C:\bar\hoge.exe」に展開されます。
なお、引数のファイル名がドット(.または..)を含まない相対パスである場合、ディレクトリリストの各ディレクトリから見た相対パスとしてファイルを検索します。引数が絶対パスの場合は、展開後の引数は単純にそのパスにファイルが見つかったらそのまま、見つからなかったら空文字列となります。
E:\Backup\2013\Text Documents\note.201311.txt (※ ENVに「E:\Backup\2013」が含まれていた場合)

これらの指定方法は組み合わせることが可能で、「%~dp1」とすると引数の絶対パスのうちドライブ文字とディレクトリのみ、「%~dp$PATH:1」とすると %1 で指定されたファイルが「PATH」内で最初に見つかったディレクトリ(ドライブ文字付き)に展開されます。

※ 組み合わせる場合、文字の順番はどのような順番であっても決まった順に出力され、その順序は「属性 日時 サイズ ファイルパス」となります。また、「f」が入っている場合は「d」「p」「n」「x」は無視されます。
※ 「$ENV:」のみ必ず最後に指定する必要があります。「:」の後に他の文字を組み合わせることはできません(「%~$PATH:f1」と記述することはできません)。

特殊な環境変数

[Windows NT 系] [拡張構文] 拡張機能が有効になっている場合、以下の動的な環境変数を利用することができます。なお、あくまで特殊な環境変数であるため、Setで一覧を出力した場合でも表示されず、Setを使ってこれらの変数に値を代入すると、それぞれの変数が意味する内容は書き換わらずに新しく同じ名前の変数が作成されます。

名前内容
%CD%現在のディレクトリが入ります(Cdコマンドで表示されるものです)。
%DATE%現在の日付が入ります(Dateコマンドで表示されるものです)。
%TIME%現在の時刻が入ります。Timeコマンドで表示されるものと若干異なり、100分の1秒まで表示されます。
%RANDOM%0から32767までの数値のうちどれかがランダムで入ります。使うたびに違う値になります。
%ERRORLEVEL%最後に実行したプログラム(バッチファイル含む)の終了コードが入ります(If Errorlevelも参照)。
%CMDEXTVERSION%拡張機能のバージョンが入ります。
%CMDCMDLINE%現在実行しているプロンプトがどのように実行されたかを示すコマンドラインが入ります。
%HIGHESTNUMANODENUMBER%現在のコンピューターにおける最大のNUMAノード番号が入ります。

サンプル1

C:\>%SystemRoot%\system32\notepad.exe

[Windows NT] Windows のシステムフォルダに入っている notepad.exe (メモ帳) を起動します。

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

@echo off
set TEMP_VAL=
foo.exe /all
if errorlevel 255 set TEMP_VAL=ERROR
if errorlevel 1 set TEMP_VAL=FAILED
bar.exe /refresh
if "%TEMP_VAL%"=="ERROR" goto OnError
if "%TEMP_VAL%"=="FAILED" goto OnFailed
echo Succeeded.
goto OnFinish

:OnError
echo An error has occurred.
goto OnFinish

:OnFailed
echo Some files have wrong data.

:OnFinish
set TEMP_VAL=

環境変数「TEMP_VAL」をバッチファイル内で作成し、「foo.exe /all」を実行した後にその結果を示す文字列をキープします。その後「bar.exe /refresh」を実行してから TEMP_VAL の値をチェックし、条件分岐を行っています。最後に、勝手に作成した変数 TEMP_VAL を環境から削除します。

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

@echo off
setlocal
set PATH2=.;%PATH%
set TEMP_VAL=%~$PATH2:1
if not "%TEMP_VAL%"=="" goto ok

echo %~nx0: no %~1 in (%PATH2%)>&2
exit /b 1

:ok
echo %TEMP_VAL%

exit /b 0

[Windows NT系] [拡張構文] Linuxにある「which」と同じような動作をバッチファイルで表現した例です。このバッチファイルに引数として(パスを含まない)ファイル名を指定すると、現在のディレクトリと環境変数PATHからそのファイル名を検索し、見つかった場合はそのファイル名を標準出力(STDOUT)に出力し、見つからなかった場合は「no xxx in ...」というテキストを標準エラー出力(STDERR)に出力します。なお、標準エラー出力への出力にはリダイレクション「>」を用いています。

関連項目