猿问

go exec with <(..) 参数

我正在尝试使用 exec 获得等效项


diff <(echo "foo") <(echo "bar")

它产生:


1c1

< foo

---

> bar

但是当我尝试:


cmd := exec.Command("diff", "<(echo foo)", "<(echo bar)")

输出是:


exit status 2

diff: <(echo foo): No such file or directory

diff: <(echo bar): No such file or directory


尚方宝剑之说
浏览 234回答 1
1回答

RISEBY

FUZxxl 的回答很简单,但是需要使用 bash。Bash 并不是真正的跨平台,并且作为解释器对代码注入是开放的。我将首先描述一种用 Go 复制这个的方法,然后描述 git 使用的答案。<(echo foo) 在 bash 中做了两件事。首先,它创建一个文件描述符以传递给被调用的命令。它做的第二件事是将 /dev/fd/n 作为参数传递。为了确认,请尝试:echo <(echo foo) <(echo bar)Echo 忽略 fds 并仅将文件描述符打印为字符串。下面的 Go 代码会做类似的事情:package mainimport (&nbsp; &nbsp; "io"&nbsp; &nbsp; "log"&nbsp; &nbsp; "os"&nbsp; &nbsp; "os/exec"&nbsp; &nbsp; "strings")func main() {&nbsp; &nbsp; cmd := exec.Command("diff", "/dev/fd/3", "/dev/fd/4")&nbsp; &nbsp; foo, err := readerFile(strings.NewReader("foo\n"))&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }&nbsp; &nbsp; defer foo.Close()&nbsp; &nbsp; bar, err := readerFile(strings.NewReader("bar\n"))&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }&nbsp; &nbsp; defer bar.Close()&nbsp; &nbsp; cmd.ExtraFiles = []*os.File{foo, bar}&nbsp; &nbsp; cmd.Stdout = os.Stdout&nbsp; &nbsp; cmd.Stderr = os.Stderr&nbsp; &nbsp; err = cmd.Run()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }}func readerFile(r io.Reader) (*os.File, error) {&nbsp; &nbsp; reader, writer, err := os.Pipe()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return nil, err&nbsp; &nbsp; }&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; io.Copy(writer, r)&nbsp; &nbsp; &nbsp; &nbsp; writer.Close()&nbsp; &nbsp; }()&nbsp; &nbsp; return reader, nil}显然,这仅适用于类 Unix 系统,因此不是非常跨平台。但是它不受代码注入的影响。GIT的方式Git 只是制作临时文件,然后比较它们。这是极其跨平台的并且不受注射影响。只需使用ioutil.TempFile创建这两个文件,然后运行exec.Command("diff", file1, file2).
随时随地看视频慕课网APP

相关分类

Go
我要回答