如何使用Go在命令行上执行diff?

Gar*_*hby 2 bash command-line-interface go

我在使用Ubuntu 14.04并diff在命令行上执行时遇到问题.查看以下Go代码:

package main

import "fmt"
import "log"
import "os/exec"

func main() {
    output, err := exec.Command("diff", "-u", "/tmp/revision-1", "/tmp/revision-4").Output()
    if err != nil {
        log.Fatalln(err)
    }

    fmt.Println(string(output))
}
Run Code Online (Sandbox Code Playgroud)

如果我执行此操作go run test.go我得到以下错误:

2015/03/18 14:39:25 exit status 1
exit status 1
Run Code Online (Sandbox Code Playgroud)

所以出现了问题,diff它将1作为退出代码返回.只有diff命令似乎会抛出错误.如果我使用catwc命令,代码运行正常.

任何想法为什么diff在这里不起作用,但其他命令呢?

Not*_*fer 5

当您运行程序时exec,如果退出代码不是0,则会出现错误.来自doc:

如果命令运行,返回的错误为nil,复制stdin,stdout和stderr没有问题,退出时退出状态为零.

如果命令无法运行或未成功完成,则错误类型为*ExitError.对于I/O问题,可能会返回其他错误类型.

所以这里发生的是当文件不同时diff会返回错误,但你会把它当成运行时错误.只需更改您的代码即可反映出它不是.通过检查错误可以实现.

例如:

    output, err := exec.Command("diff", "-u", "/tmp/revision-1", "/tmp/revision-4").CombinedOutput()
    if err != nil {

        switch err.(type) {
        case *exec.ExitError:
            // this is just an exit code error, no worries
            // do nothing

        default: //couldnt run diff
            log.Fatal(err)
        }
    }
Run Code Online (Sandbox Code Playgroud)

此外,我已经改变了它CombinedOutput,所以如果发生任何差异特定错误,你也会看到stderr.

请注意,即使其中一个文件不存在,您也会收到"有效"错误.所以你可以ExitError通过这样做来检查退出代码:

    switch e := err.(type) {
    case *exec.ExitError:

        // we can check the actual error code. This is not platform portable 
        if status, ok := e.Sys().(syscall.WaitStatus); ok {
            // exit code 1 means theres a difference and is not an error
            if status.ExitStatus() != 1 { 
                log.Fatal(err)
            }
        }
Run Code Online (Sandbox Code Playgroud)