英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论