英文:
exec.Command with cp exits with status 1
问题
util.ExecuteCommandWithOuput(exec.Command("cp", "-r", "./*.json", artifact.dir))
func ExecuteCommandWithOuput(cmd *exec.Cmd) {
output, err := cmd.Output()
if err != nil {
log.Print("执行命令出错:", cmd.Args, err)
}
fmt.Print(string(output))
}
输出
2017/01/16 13:26:35 执行命令出错:[cp -r ./*.json myartifact] 退出状态 1
问题
- 当 cp 命令失败时,如何获取完整的错误消息?我已经使用了 err != nil 并打印了 err。
- exec.Command 不支持文件的复制和目录的递归复制吗?
- 有什么建议可以实现文件的复制和目录的递归复制吗?
我刚刚开始学习 Go,所以对 Go 还不太熟悉。
英文:
util.ExecuteCommandWithOuput(exec.Command("cp", "-r", "./*.json", artifact.dir))
func ExecuteCommandWithOuput(cmd *exec.Cmd) {
output, err := cmd.Output()
if err != nil {
log.Print("Error executing ", cmd.Args, err)
}
fmt.Print(string(output))
}
Output
2017/01/16 13:26:35 Error executing [cp -r ./*.json myartifact] exit status 1
Questions
- How do i get details of complete error message on failure of cp
command ? I did have err != nill and Print err - Does exec.Command not support copy of files and recursive copy of directories ?
- Any suggestions how i implement copy of files and recursive copy of
directories ?
I have just started adopting Go and hence a new comer with Go.
答案1
得分: 2
在exec.Command
中无法使用通配符。我会遍历目录中的文件,检查文件扩展名是否以.json
结尾,然后复制该文件。
英文:
You can't do wild cards in exec.Command
. I'd iterate through the files in the directory and check if the extension ends in .json
and then copy that file.
答案2
得分: 1
问题
解释一下:所谓的“通配符”是由通常执行命令行命令的 shell 扩展的。也就是说,当你调用 cp -r ./*.json dir/
时,shell 会介入,自行扩展 *.json
,生成一个匹配该模式并位于当前目录中的文件名称列表,并将该列表作为参数传递给 cp
命令。
因此,如果你有10个匹配的文件,实际调用 cp
的命令将如下所示:
cp -r file1.json file2.json ... dir/
当你直接调用 cp ...
时,而不是让 shell 介入并为你扩展 *.json
这个“文件通配符”,cp
命令会接收到一个文件名为“*.json”的文件,并尝试打开它。由于名为“*.json”的文件实际上不存在,cp
失败并退出。
解决方案
第一个(虽然有点笨拙)的解决方案是通过 shell 来调用 cp
。也就是将你的 cp
调用转换为一个 shell 脚本,并将其传递给一个 shell。
最简单的方法是使用类似以下的方式:
exec.Command(`/bin/sh -c 'cp -r ./*.json manifest'`)
这将调用 /bin/sh
shell,并通过其 -c
命令行选项传递要执行的脚本。
另一种解决方案是使用标准的 Go 库自己实现复制操作:path/filepath
包的函数提供了对文件通配符的支持,就像 shell 扩展一样,并且可以迭代给定目录的条目。使用其中任何一种方法,你都可以构建要复制的文件列表和/或对它们进行迭代。
然后,你可以使用 os.OpenFile()
函数打开源文件和目标文件,使用 io.Copy()
函数在它们之间复制内容。
英文:
The problem
To explain: the so-called "wildcards" are expanded by the shell in which you typically execute command-line commands. That is, when you invoke cp -r ./*.json dir/
, the shell kicks in, expands *.json
by itself—producing a list of names of the files matching that pattern and located in the current directory and pass the cp
command a list of such names.
So if you have, say, 10 matching files, the actuall call to cp
will end up looking like
cp -r file1.json file2.json ... dir/
When you pass call cp ...
directly—without the shell kicking in and expanding that *.json
"fileglob" for you, the cp
command receives the name of a file "*.json" verbatim and attempts to open it. Since the file named exactly "*.json" supposedly does not exist, cp
fails and exits.
The solutions
The first (admittedly lame) solution is to pass a call to cp
"through" a shell. That is, turn your call to cp
into a shell script and pass it to a shell.
The simplest way to do this is to use something like
exec.Command(`/bin/sh -c 'cp -r ./*.json manifest'`)
This will call a shell /bin/sh
and pass it the script to execute via its -c
command-line option.
Another solution is to roll copying yourself using the standard Go library: the functions of the path/filepath
package provide support for both expanding fileglobs as the shell would do it and iterating over the entries of a given directory. Using either of these approaches you can build the list of files to copy and/or iterate over them.
Then you can use the function os.OpenFile()
to open the source and destination files, and io.Copy()
to copy the contents between them.
答案3
得分: 0
使用 https://github.com/juju/utils/blob/master/fs/copy.go,该代码内部使用了 io 和 os 包。
英文:
Using https://github.com/juju/utils/blob/master/fs/copy.go that internally uses io, os packages
答案4
得分: 0
我发现需要将bash的参数拆分为单独的参数,但是cp
命令及其参数需要放在exec.Command
的单个参数中,像这样:
out, err := exec.Command("/bin/bash", "-c", "cp -r ./*.json manifest").CombinedOutput()
英文:
I found that the arguments to bash needed to be split into separate parameters, but the cp command and its parameters need to be put into a single param of exec.Command
, like so::
out, err := exec.Command("/bin/bash", "-c", "cp -r ./*.json manifest").CombinedOutput()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论