multipost →Qrunch
CMD /?
で出てくるヘルプを一部引用する:
/C または /K が指定されている場合、スイッチの後の残りのコマンド ラインがコマンド ラインとして処理されます。次のルールが引用符 (") の処理に使われます:
正直、まったく意味が分からんかったのだが、よくよく考えると、基本の動作は「2.」で、「1.」が特殊なケースということなのだろう。
では「1.」はどういうケースかというと:
CMD /C "C:\Program Files\HogeHoge\Aplication.exe"
といったケースのことだろう。これは、1. のような解釈をしないと「C:\Program
」というコマンドに「Files\HogeHoge\Application.exe
」という引数を渡しているとみなしてしまう。
ということで、通常、引用符が含まれているかもしれないコマンド列を CMD.EXE に渡すには /S を指定して強制的に「2.」を指定して:
CMD.EXE /S /C ""C:\Program Files\Hogehoge\Application.exe "ahaha""
とするのがよろしいようだ。さて、ここで注意すべき点がある。
- 「二重引用符の中の二重引用符は
\"
に置換するなど特別扱いして書く」など配慮は無用。機械的に " をコマンド列の前後にくっつけるだけでよい - ただし、CMD.EXE を呼び出すための、外部プロセスの呼び出しの各言語ライブラリが二重引用符を特別扱いすることが多い(
"
→\"
変換を勝手にする)。これを回避するテクが必要
Goの "os/exec" の場合
普通に "os/exec".Cmd.Args
に引数パラメータを置くと、"
→ \"
が行われてしまう。Windows版 "os/exec"
の隠しパラメータ?である SysProcAttr.CmdLine
を使おう
package main import ( "os" "os/exec" "syscall" ) func main() { cmd := &exec.Cmd{ Path: os.Getenv("COMSPEC"), Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr, SysProcAttr: &syscall.SysProcAttr{CmdLine: `/S /C "DIR /w "C:\Program Files""`}, } cmd.Run() }
以上