startコマンドとスペースの相性

昨日のstartコマンドについて、さらに問題が起きたので追記。
というのも、よくある「コマンドとスペースの相性が抜群に悪い」ということです。
ただ、それにしても、startコマンドは非常に奇妙な動きをしたので、まとめ。


当然ながら、以下の呼び出しはエラーになります。

start C:\Program Files\Hoge\Hoge.bat

Program と Filesの間の空白でコマンドが区切られてしまうからです。
では、以下のように変えてみましょう。

start "C:\Program Files\Hoge\Hoge.bat"

空白を含むパスのために、二重引用符で囲みました。一見大丈夫そうです。
しかし、これも実はダメなのです。
startコマンドは、新規で作るコマンドプロンプトのタイトルが設定できます。
それが、""で囲った最初のテキストになるのです。


つまり、上の命令は、肝心のコマンドがタイトルの指定になってしまいます。
ということで、以下になります。

start "Hoge" "C:\Program Files\Hoge\Hoge.bat"

なんでもいいんですが、タイトルを付けます。
すると、二つ目の二重引用符は無事コマンドになるのです。


と、これだけで解決すればよかったのですが……。
実は、さらに問題は隠れています。バッチ処理、引数、渡したい時ありますよね?
その引数に空白があったらどうしましょうか、当然こうするでしょう。

start "Hoge" "C:\Program Files\Hoge\Hoge.bat" "C:\Program Files\Hoge\Foo.txt"

これは、実はエラーになります。
困ったことに、startが「"C:\Program Files\Hoge\Hoge.bat" "C:\Program」をコマンドとして認識してしまうのです。
バグなんじゃないか、、、とすら思うんですが、こういう挙動になってます。


つまり、コマンド・その引数、両方にスペースがある場合、そのままではどうやってもうまく行かないのです。
では、諦めるしか無いのでしょうか?
そんなことはありませんでした。

for %A in (C:\Program Files\Hoge\Hoge.bat) do start "Hoge" %~sA "C:\Program Files\Hoge\Foo.txt"

for構文を使います。
forを使うことで、コマンドを一度引数に取り込み、パス修飾「%~s」でショートネーム(8.3形式)にするのです。
そうすれば、コマンドには空白は含まれない安全なパスになります。


そして、幸運なことにコマンドがちゃんと空白なしで渡せれば、引数は二重引用符で囲っていても問題ありません。
(このあたりの仕様の微妙さは、若干不安が残りますが……)
結果、非常に面倒になりましたが、どのパスに空白があっても、なんとか問題なく実行できるようになりました。


それにしても思うのです。
なんで、こんなに空白に弱いのに、パスに空白を含めることを許可した上、
システムが作るフォルダに空白があるのか(Program Files)。
このあたりは、もうちょっとシステム的にサポートして欲しいと感じるものです。