exec.Command使用cp命令退出状态为1。

huangapple go评论64阅读模式
英文:

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

问题

  1. 当 cp 命令失败时,如何获取完整的错误消息?我已经使用了 err != nil 并打印了 err。
  2. exec.Command 不支持文件的复制和目录的递归复制吗?
  3. 有什么建议可以实现文件的复制和目录的递归复制吗?

我刚刚开始学习 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

  1. How do i get details of complete error message on failure of cp
    command ? I did have err != nill and Print err
  2. Does exec.Command not support copy of files and recursive copy of directories ?
  3. 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()

huangapple
  • 本文由 发表于 2017年1月17日 05:38:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/41685393.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定