問題の症状
親プロセスのソース:
// exec1.go package main import ( "os" "os/exec" ) func main() { c := exec.Command("foo", `"<BAR>"`) c.Stdout = os.Stdout c.Stderr = os.Stderr c.Stdin = os.Stdin c.Run() }
子プロセスのソース(バッチファイル):
@rem foo.cmd @echo %0 %* @exit /b 0
実行すると
$ go run exec1.go foo \"<BAR>\"
二重引用符の前にバックスラッシュがついてしまう。
解決方法
バックスラッシュが付かないようにするには、Go言語標準のexec.Cmd.Args[]
を Windows 形式の引数形式に展開する処理をパスして、自前で直接指定すればよい。
//exec2.go package main import ( "os" "os/exec" "syscall" ) func main() { c := exec.Command("foo") c.SysProcAttr = &syscall.SysProcAttr{CmdLine: `foo "<BAR>"`} c.Stdout = os.Stdout c.Stderr = os.Stderr c.Stdin = os.Stdin c.Run() }
$ go run exec2.go foo "<BAR>"
なぜ、こんなことをする必要があるのか
FIND.EXE や CMD.EXE は、引数につけられた二重引用符の有無で、その引数がどういうものか判別しています。このため、Goのプログラムから FIND.EXE が意図どおりに呼べないという問題が発生していました。