douqiu0796 2015-03-18 14:51
浏览 77
已采纳

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

I'm having a problem using Ubuntu 14.04 and executing diff on the command line. Look at the following Go code:

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))
}

If i execute this using go run test.go i get the following error:

2015/03/18 14:39:25 exit status 1
exit status 1

So something is going wrong with diff and it's returning 1 as its exit code. Only the diff command seems to throw an error. If i use the cat or wc command, the code runs fine.

Any ideas why diff doesn't work here but other commands do?

  • 写回答

1条回答 默认 最新

  • dsfgds4215 2015-03-18 15:16
    关注

    When you run a program with exec, you get an error if the exit code was not 0. From the doc:

    The returned error is nil if the command runs, has no problems copying stdin, stdout, and stderr, and exits with a zero exit status.

    If the command fails to run or doesn't complete successfully, the error is of type *ExitError. Other error types may be returned for I/O problems.

    So what happens here is that diff returns an error when the files are different, yet you treat it like a runtime error. Just change your code to reflect that it isn't. It's possible by checking the error.

    e.g. something like this:

        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)
            }
        }
    

    Also, I've changed it get CombinedOutput, so if any diff specific errors occured, you'll see stderr as well.

    Note that you'll get a "valid" error even if one of the files doesn't exist. So you can check the ExitError's exit code by doing something like this:

        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)
                }
            }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?