特殊文字のエスケープ
echo A & Bのように書いたのに、Aしか表示されず、Bが「コマンドが見つかりません」というエラーになった経験はありませんか。
これは、&がコマンドプロンプトにとって「コマンドの区切り」という特別な意味を持つ文字だからです。
このような特殊文字を、特別な意味を持たないただの文字として扱うための仕組みがエスケープです。
この記事では、コマンドプロンプトとバッチファイルで使えるエスケープの方法を解説します。
特殊文字とは
コマンドプロンプトが特別な意味を持つものとして解釈する主な文字は、次のとおりです。
| 文字 | 本来の意味 |
|---|---|
& | 複数のコマンドを順番に実行する |
| | 左のコマンドの出力を右のコマンドに渡す |
< | ファイルから入力を受け取る |
> | 出力をファイルに書き込む |
( ) | コマンドをブロックにまとめる |
^ | エスケープ文字(次の文字を特別扱いしない) |
% | 変数やバッチファイルの引数を展開する |
! | 遅延展開が有効な場合に変数を展開する |
これらの文字を文字そのものとして使いたいときに、エスケープが必要になります。
キャレット(^)でエスケープする
コマンドプロンプトのエスケープ文字は、キャレット(^)です。
特殊文字の直前に^を付けると、その文字は特別な意味を失い、ただの文字として扱われます。
^特殊文字
使用例
&を含む文字列をechoで表示する例です。
>や|も同様に、^を付ければ表示できます。

中小企業経営者のためのRPA入門 RPA導入を成功させる方法

60分でわかる! AIエージェント 超 入門

コマンドラインの黒い画面が怖いんです。

知識・才能ゼロでもらく~に月10万円稼ぐ! よくわかるAI副業超入門
^を付けなかった場合、>以降はファイル名として扱われ、画面ではなくファイルに出力されてしまいます。
echo 1 > 0のように^を付けずに実行すると、0という名前のファイルが作成されます。意図しないファイルができていないか確認してください。
^自体を表示する
^自体もエスケープ文字なので、表示したい場合は^^と重ねて書きます。
%をエスケープする(%%)
%は、^ではエスケープできません。
バッチファイルの中で%を文字として使いたい場合は、%%と 2 つ重ねて記述します。
@echo off
echo Progress: 50%%
echo Remainder: 7 %% 3
実行すると、Progress: 50%とRemainder: 7 % 3と表示されます。
set /aコマンドで剰余(割り算の余り)を求める場合も、バッチファイル内では%%と書きます。
@echo off
set /a REMAINDER=7 %% 3
echo %REMAINDER%
このバッチファイルを実行すると、1と表示されます。
%%と重ねる必要があるのは、バッチファイルの中だけです。コマンドプロンプトに直接入力する場合は、echo 50%のように%を 1 つだけ書きます。同様に、forコマンドのループ変数も、バッチファイルでは%%a、直接入力では%aと書きます。
ダブルクォートで囲む
&、|、<、>、(、)は、ダブルクォート(")で囲むと、特別な意味を失います。
"特殊文字を含む文字列"
使用例
ファイル名に&を含むファイルを扱う例です。^を使わなくても、全体を"で囲めばそのまま渡せます。
ただし、echoにダブルクォートで囲んだ文字列を渡すと、"自体も表示されます。
ダブルクォートの中では、^はエスケープ文字ではなく、ただの文字として扱われます。そのため、"A ^& B"と書くと、^もそのまま表示されます。一方で、%による変数の展開は、ダブルクォートの中でも行われます。バッチファイルで%を文字として使う場合は、ダブルクォートの中でも%%と書く必要があります。また、遅延展開が有効な場合は、!もダブルクォートの中で展開されます。
setコマンドで特殊文字を含む値を代入する
setコマンドで変数に特殊文字を含む値を代入するときは、"変数名=値"の形で全体を囲むのが安全です。
囲まずに書くと、&以降が別のコマンドとして実行されてしまいます。
@echo off
rem 悪い例: & 以降が別コマンドとして実行されてしまう
set TITLE=Tom & Jerry
rem 良い例: 全体を " で囲む
set "TITLE=Tom & Jerry"
echo "%TITLE%"
良い例のように書くと、Tom & Jerryが変数TITLEに正しく代入されます。
echo %TITLE%のように囲まずに展開すると、展開後のecho Tom & Jerryの&が再び区切りとして解釈されます。echo "%TITLE%"のように"で囲んでください("自体も表示されます)。
この書き方は、値の末尾に意図しないスペースが入るのを防げる点でも便利です。
ブロック内の)をエスケープする
ifやforの( )の中で)を含む文字列を表示すると、)がブロックの終わりと解釈されてしまいます。
@echo off
if exist "C:\Windows" (
echo 見つかりました ^(Windows フォルダー^)
)
上記のように、ブロックの中で文字として使う)は、^)とエスケープします。
特に、%ProgramFiles(x86)%のような環境変数を展開する場合は注意が必要です。%...%はブロックの解析前に展開されるため、展開結果のC:\Program Files (x86)に含まれる)がブロックを閉じてしまい、1 つ目の例はエラーになります。変数の展開結果には^を付けられないため、2 つ目の例のように"で囲んでください。遅延展開(!ProgramFiles(x86)!)を使う方法もあります。
なお、(はブロックの途中で現れても問題ないため、エスケープが必要なのは)だけです。
@echo off
if 1==1 (
echo %ProgramFiles(x86)%
)
if 1==1 (
echo "%ProgramFiles(x86)%"
)
遅延展開については、関連記事を参照してください。
行末の^で長いコマンドを改行する
行の最後に^を書くと、次の行がその行の続きとして扱われます。
長いコマンドを読みやすく折り返したいときに便利です。
@echo off
robocopy C:\Source C:\Backup ^
/E ^
/R:3 ^
/W:5
^の後ろにスペースがあると、改行ではなく「スペースをエスケープ」したことになり、折り返しが機能しません。^は必ず行末の最後の文字にしてください。
for /fやcmd /cの中でエスケープする
for /fのin ('...')の中や、cmd /cに渡すコマンドの中では、コマンドが別のcmdで再解釈されます。
そのため、パイプやリダイレクトは^でエスケープして、内側のコマンドに渡します。なお、cmd /c "tasklist | find /i notepad"のように全体を"で囲む場合は、^は不要です。
@echo off
for /f "tokens=*" %%a in ('tasklist ^| find "notepad.exe"') do (
echo %%a
)
^|と書くことで、|がforコマンドの外側ではなく、tasklistとfindの間のパイプとして解釈されます。
エスケープ方法のまとめ
| 表示したい文字 | 通常の書き方 | ダブルクォート内 |
|---|---|---|
& | < > | ^& ^| ^< ^> | そのまま書ける |
( ) | ^( ^) | そのまま書ける |
^ | ^^ | そのまま書ける |
%(バッチファイル) | %% | %% |
!(遅延展開が有効な場合) | ^^! | ^! |
" | ^"(引用符の外のみ)(※) | エスケープ不可 |
※ "は、ダブルクォートの外側では^"で文字として扱えますが、内側では^が文字になるためエスケープできません。プログラムに"を渡したい場合は\"と書くものが多いですが、cmd自体は\を無視して"を引用符の開始・終了として扱うため、その後ろの&などが特殊文字として実行される場合があります。
練習問題
まとめ
- 特殊文字(
&|<>())は、直前に^を付けるとエスケープできる ^自体は^^、バッチファイル内の%は%%と書く- ダブルクォートで囲むと、
&や|などの特殊文字はそのまま扱える(ただし^は文字になり、%は展開される) setで特殊文字を含む値を代入するときは、set "変数名=値"の形にする- 行末の
^で、長いコマンドを複数行に分けられる