英文:
Why doesn't the file appear after exec.Command("iconv", ...)?
问题
我正在尝试转换文件的编码,但结果文件没有出现。从控制台运行的命令是正确的。
func main() {
	from := "WINDOWS-1251"
	filename := "3_win1251.csv"
	cmd := exec.Command("iconv", fmt.Sprintf("-f %s", from), fmt.Sprintf("-t UTF-8//TRANSLIT %s", filename), fmt.Sprintf("-o ./convert_%s", filename))
    // 命令: /usr/bin/iconv -f WINDOWS-1251 -t UTF-8//TRANSLIT 3_win1251.csv -o ./convert_3_win1251.csv
	log.Println(cmd.String())
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
	log.Println(cmd.ProcessState)
}
结果:exit status 0,但文件缺失。
操作系统:Debian 11
英文:
I am trying to convert the encoding of the file, but the resulting file does not appear. The command from the console runs correctly.
func main() {
	from := "WINDOWS-1251"
	filename := "3_win1251.csv"
	cmd := exec.Command("iconv", fmt.Sprintf("-f %s", from), fmt.Sprintf("-t UTF-8//TRANSLIT %s", filename), fmt.Sprintf("-o ./convert_%s", filename))
    // command: /usr/bin/iconv -f WINDOWS-1251 -t UTF-8//TRANSLIT 3_win1251.csv -o ./convert_3_win1251.csv
	log.Println(cmd.String())
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
	log.Println(cmd.ProcessState)
}
result: exit status 0 and the lack of a file.
file: 3_win1251.csv
os: debian 11
答案1
得分: 1
值得一提的是,strace 是一个用于诊断此类问题的完美工具:
$ strace iconv -f WINDOWS-1251 -t UTF-8//TRANSLIT 3_win1251.csv -o ./convert_3_win1251.csv 2>&1 | grep -F execve
execve("/usr/bin/iconv", ["iconv", "-f", "WINDOWS-1251", "-t", "UTF-8//TRANSLIT", "3_win1251.csv", "-o", "./convert_3_win1251.csv"], 0x7fffeed6e768 /* 55 vars */) = 0
与之相比:
$ strace -f ./main 2>&1 | grep -F execve
execve("./m", ["./m"], 0x7ffd85261008 /* 55 vars */) = 0
[pid 2745776] execve("/usr/bin/iconv", ["iconv", "-f WINDOWS-1251", "-t UTF-8//TRANSLIT 3_win1251.csv", "-o ./convert_3_win1251.csv"], 0xc0001ba000 /* 55 vars */ <unfinished ...>
[pid 2745776] <... execve resumed>)     = 0
很容易发现参数是不同的。请注意,-f 选项会导致它跟踪子进程。
在 Windows 上,我们可以使用 Process Monitor 工具。让我们借用问题 https://stackoverflow.com/questions/28954729/exec-with-double-quoted-argument 中的命令。
在 cmd.exe 中运行:
find "SomeText" file.txt
Command line 是 find "SomeText" file.txt(请参见下面的屏幕截图)。
但是,当使用 exe.Command 运行时,Command line 是 find \"SomeText\" file.txt(请参见下面的屏幕截图)。" 被错误地转义了。正如该问题的答案所建议的,解决方案是直接设置整个命令行。
英文:
It's worth mentioning that strace is a perfect tool for diagnosing such kind of problems:
$ strace iconv -f WINDOWS-1251 -t UTF-8//TRANSLIT 3_win1251.csv -o ./convert_3_win1251.csv 2>&1 | grep -F execve
execve("/usr/bin/iconv", ["iconv", "-f", "WINDOWS-1251", "-t", "UTF-8//TRANSLIT", "3_win1251.csv", "-o", "./convert_3_win1251.csv"], 0x7fffeed6e768 /* 55 vars */) = 0
Comparing to:
$ strace -f ./main 2>&1 | grep -F execve
execve("./m", ["./m"], 0x7ffd85261008 /* 55 vars */) = 0
[pid 2745776] execve("/usr/bin/iconv", ["iconv", "-f WINDOWS-1251", "-t UTF-8//TRANSLIT 3_win1251.csv", "-o ./convert_3_win1251.csv"], 0xc0001ba000 /* 55 vars */ <unfinished ...>
[pid 2745776] <... execve resumed>)     = 0
It's easy to spot that the arguments are different. Note that the -f option cause it to trace child processes.
While on Windows, we can use the Process Monitor tool. Let's borrow the command from the question https://stackoverflow.com/questions/28954729/exec-with-double-quoted-argument.
When running in cmd.exe:
find "SomeText" file.txt
The Command line is find "SomeText" file.txt (see the screenshot below).
But when running with exe.Command, the Command line is find \"SomeText\" file.txt (see the screenshot below). The " are incorrectly escaped. And as suggested by the answer for that question, the solution is to set the whole command line directly.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论