[Golang] Check If A Program (Command) Exists


Check if a program (or command), such as wget or ffmpeg, is available in Go.

This looks like a easy task. I made some Google searches and found [2] you can check if a command exists in shell as follows:

$ command -v <the_command>

Now we use standard os.exec package to run the command for us:

import (
      "os/exec"
)

func isCommandAvailable(name string) bool {
      cmd := exec.Command("command", "-v", name)
      if err := cmd.Run(); err != nil {
              return false
      }
      return true
}

Looks very easy. To be more confident, we write a test to see if it works:

import (
      "testing"
)

func TestIsCommandAvailable(t *testing.T) {
      if isCommandAvailable("ls") == false {
              t.Error("ls command does not exist!")
      }
      if isCommandAvailable("ls111") == true {
              t.Error("ls111 command should not exist!")
      }
}

And the test failed!!!

=== RUN   TestIsCommandAvailable
--- FAIL: TestIsCommandAvailable (0.00s)
      util_test.go:9: ls command does not exist!

I print the error message and got:

exec: "command": executable file not found in $PATH

This is really strange, and I googled again and found [4] that you cannot run built-in command directly via exec.Command, so the following way of running built-in command will not work:

cmd := exec.Command("command", "-v", name)

Instead, you should run the built-in command as follows:

cmd := exec.Command("/bin/sh", "-c", "command -v "+name)

And finally it works as expected and the test passed! The correct way to check if a program exists in Go is:

import (
      "os/exec"
)

func isCommandAvailable(name string) bool {
      cmd := exec.Command("/bin/sh", "-c", "command -v "+name)
      if err := cmd.Run(); err != nil {
              return false
      }
      return true
}

Tested on: Ubuntu 17.10, Go 1.10


References:

[1]
[2]shell - Check if a program exists from a Bash script - Stack Overflow
[3]
[4]go - How to execute a linux built in command in golang - Stack Overflow
[5]
[6]Help! os/exec Output() on Non-English Windows cmd! : golang
[7]A netstat implementation written in Go : golang
[8]Shell scripter here, I can't get Go to click : golang