英文:
Golang execute commands with double quotes
问题
我做了一个简单的程序,它接受用户输入并将其作为系统命令执行。
这段代码接受用户输入并将其存储在command变量中:
fmt.Print("> ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
command := scanner.Text()
然后我执行该命令并打印出标准输出和标准错误:
cmd := exec.Command("cmd", "/c", command)
cmd.Stdout = customOutput{}
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("无法运行命令:", err)
}
现在,当我执行像ipconfig、arp -a、ping这样的命令时,一切都很顺利,并且输出会在执行时打印出来,但是当我尝试在命令中使用双引号时,它就会出错。
问题:
我尝试执行以下命令:echo hello world > file.txt
,这个命令可以正常工作,但是一旦我将文件名放在引号中:echo hello world > "file.txt"
,我就会得到退出状态1,并且从标准错误中得到的错误信息是:文件名、目录名或卷标语法不正确。
我尝试过:
- 搜索,甚至向chat-gpt询问,但我无法弄清楚为什么会出现这种情况。
- 在执行命令之前将引号替换为:"或^",但都没有起作用。
我使用的是Windows 10。
完整代码以便更好地理解:
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
)
type customOutput struct{}
func (c customOutput) Write(p []byte) (int, error) {
fmt.Println("接收到输出:", string(p))
return len(p), nil
}
func main() {
fmt.Print("> ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
command := scanner.Text()
cmd := exec.Command("cmd", "/c", command)
cmd.Stdout = customOutput{}
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("无法运行命令:", err)
}
}
英文:
I made a simple program which takes user input and then executes it as a system command.
This takes user input and stores it in command variable:
fmt.Print("> ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
command := scanner.Text()
Then I execute it and print out Stdout aswell as Stderr:
cmd := exec.Command("cmd", "/c", command)
cmd.Stdout = customOutput{}
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("could not run command: ", err)
}
Now when I execute command like: ipconfig, arp -a, ping, it all works great and the output is getting printed out as it executes, but when I try to use double quotes in the command it just breaks.
The problem:
I tried doing: echo hello world > file.txt
and this works fine but as soon as I put the filename in quotes: echo hello world > "file.txt"
I'm getting exit status 1 and from Stderr I'm getting: The filename, directory name, or volume label syntax is incorrect.
I tried:
- searching, even asking chat-gpt but I can't figure out why this happens.
- replacing the quotes before executing the command to: " or ^" but nothing works.
I'm using windows 10 btw.
Full code for better understanding:
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
)
type customOutput struct{}
func (c customOutput) Write(p []byte) (int, error) {
fmt.Println("received output: ", string(p))
return len(p), nil
}
func main() {
fmt.Print("> ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
command := scanner.Text()
cmd := exec.Command("cmd", "/c", command)
cmd.Stdout = customOutput{}
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("could not run command: ", err)
}
}
答案1
得分: 2
你需要执行以下操作:
cmd := exec.Command("cmd.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf(`/c "%s"`, command)}
cmd.Stdout = customOutput{}
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("无法运行命令:", err)
}
然后可能需要在命令中转义引号。
在Windows上,进程将整个命令行作为单个字符串接收并进行自己的解析。Command使用与使用CommandLineToArgvW的应用程序兼容的算法将Args组合和引用为命令行字符串。值得注意的例外是msiexec.exe和cmd.exe(以及所有批处理文件),它们具有不同的取消引用算法。在这些或类似情况下,您可以自己进行引用并在SysProcAttr.CmdLine中提供完整的命令行,将Args留空。
英文:
You need to do
cmd := exec.Command("cmd.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf(`/c "%s"`, command)}
cmd.Stdout = customOutput{}
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("could not run command: ", err)
}
and then probably escape the quotes in command.
https://pkg.go.dev/os/exec#Command
> On Windows, processes receive the whole command line as a single string and do their own parsing. Command combines and quotes Args into a command line string with an algorithm compatible with applications using CommandLineToArgvW (which is the most common way). *Notable exceptions are msiexec.exe and cmd.exe (and thus, all batch files), which have a different unquoting algorithm. In these or other similar cases, you can do the quoting yourself and provide the full command line in SysProcAttr.CmdLine, leaving Args empty.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论