os.exec.Command and pbcopy

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

os.exec.Command and pbcopy

问题

我正在尝试在Go中执行bash命令"hello world" | /usr/bin/pbcopy

package main

import (
    "fmt"
    "os/exec"
    "strings"
)

func Cmd(cmd string) {
    fmt.Println("command is ", cmd)
    parts := strings.Fields(cmd)
    head := parts[0]
    parts = parts[1:len(parts)]
    out, err := exec.Command(head, parts...).Output()
    if err != nil {
        fmt.Printf("%s", err)
    }
    fmt.Println("out")
    fmt.Println(string(out))
}

func main() {
    Cmd(`echo "hello world" | /usr/bin/pbcopy`)
}

当我运行这个go文件时,输出如下:

command is  echo "hello world" | /usr/bin/pbcopy
out
"hello world" | /usr/bin/pbcopy

我期望剪贴板的内容应该是"hello world",但实际上并不是。

更新

我尝试使用io.Pipe

package main

import (
    "bytes"
    "io"
    "os"
    "os/exec"
)

func main() {
    c1 := exec.Command(`echo "hello world"`)
    c2 := exec.Command("/usr/bin/pbcopy")

    r, w := io.Pipe()
    c1.Stdout = w
    c2.Stdin = r

    var b2 bytes.Buffer

    c2.Stdout = &b2

    c1.Start()
    c2.Start()
    c1.Wait()
    w.Close()
    c2.Wait()
    io.Copy(os.Stdout, &b2)
}

... 但剪贴板仍然不等于"hello world"。

英文:

I am trying to execute bash command "hello world" | /usr/bin/pbcopy inside go:

package main

import (
    "fmt"
    "os/exec"
    "strings"
)

func Cmd(cmd string) {
    fmt.Println("command is ", cmd)
    parts := strings.Fields(cmd)
    head := parts[0]
    parts = parts[1:len(parts)]
    out, err := exec.Command(head, parts...).Output()
    if err != nil {
        fmt.Printf("%s", err)
    }
    fmt.Println("out")
    fmt.Println(string(out))
}

func main() {
    Cmd(`echo "hello world" | /usr/bin/pbcopy`)
}

When I run this go file, it outputs:

command is  echo "hello world" | /usr/bin/pbcopy
out
"hello world" | /usr/bin/pbcopy

I expect clipboard to be equal to "hello world" but it is not.

Update

I've tried to use io.Pipe

package main

import (
    "bytes"
    "io"
    "os"
    "os/exec"
)

func main() {
    c1 := exec.Command(`echo "hello world"`)
    c2 := exec.Command("/usr/bin/pbcopy")

    r, w := io.Pipe()
    c1.Stdout = w
    c2.Stdin = r

    var b2 bytes.Buffer

    c2.Stdout = &b2

    c1.Start()
    c2.Start()
    c1.Wait()
    w.Close()
    c2.Wait()
    io.Copy(os.Stdout, &b2)
}

... but clipboard is still not equal to "hello world"

答案1

得分: 2

Command函数接受一个可执行文件和一个参数列表。所以当你调用:

exec.Command(`echo "hello world"`)

这实际上是尝试运行一个名为echo "hello world"的命令(包括空格和引号)。正如你已经了解的那样,exec.Command不会将内容传递给shell,所以使用"|"这样的管道符号也不会起作用。如果你想将标准输出和标准输入连接在一起,代码如下:

func main() {
    c1 := exec.Command("echo", "hello world")
    c2 := exec.Command("/usr/bin/pbcopy")

    c1stdout, _ := c1.StdoutPipe()
    c2stdin, _ := c2.StdinPipe()

    c1.Start()
    c2.Start()

    io.Copy(c2stdin, c1stdout)

    c2stdin.Close()
    c2.Wait()
}

但其实没有必要这么麻烦。你有一个shell,如果你要求它,它可以为你完成所有这些操作。

func main() {
    exec.Command("sh", "-c", `echo "hello world" | pbcopy`).Run()
}
英文:

Command takes an executable and a list of arguments. So when you call

exec.Command(`echo "hello world"`)

That literally tries to run a command called echo "hello world" (with space and quotes). As you've already learned, exec.Command does not pass things to the shell, so "|" won't work either this way. So if you're going to piece it all together by tying the stdout and stdin together, it would look like this:

func main() {
	c1 := exec.Command("echo", "hello world")
	c2 := exec.Command("/usr/bin/pbcopy")

	c1stdout, _ := c1.StdoutPipe()
	c2stdin, _ := c2.StdinPipe()

	c1.Start()
	c2.Start()

	io.Copy(c2stdin, c1stdout)

	c2stdin.Close()
	c2.Wait()
}

But there's no need for all that. You have a shell. It can do all of this for you if you ask it to.

func main() {
	exec.Command("sh", "-c", `echo "hello world" | pbcopy`).Run()
}

huangapple
  • 本文由 发表于 2015年5月7日 16:36:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/30095870.html
匿名

发表评论

匿名网友

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

确定