thor
thor

Reputation: 22510

How to check if an executable command exists in R

Is there a way in R to check if a command exists in the operating system?

I know that file.exists(file) can be used to check if a file exists. But what about a command on the system PATH?

(This is with Ubuntu 20.04, R 4.1).

Related:

How to check if object (variable) is defined in R?

How can I check if a directory exists in a Bash shell script?

Upvotes: 0

Views: 415

Answers (2)

jwalton
jwalton

Reputation: 5686

Short Answer

On linux:

is_bin_on_path = function(bin) {
  exit_code = suppressWarnings(system2("command", args = c("-v", bin), stdout = FALSE))
  return(exit_code == 0)
}

Example usage:

is_bin_on_path("ls")
# TRUE

is_bin_on_path("git")
# TRUE

is_bin_on_path("madeup")
# FALSE

Tell me more

This answer recommends avoiding using which to determine whether an executable is found on the system PATH. They recommend avoiding which as it doesn't consistently set exit codes across different operating systems, and as it can apparently do other "evil things".

Instead, OP advocates using command as a safer alternative to which.

We can invoke command from system2() as:

system2("command", args = c("-v", executable))

where executable is a string representing the program you are checking for the existence of. eg. "git", "python", ...

If executable is on the system PATH, the location of the executable is printed. If we wish, we can suppress this by calling system2() with stdout = FALSE:

system2("command", args = c("-v", executable), stdout = FALSE)

If executable isn't on the system PATH, system2() will raise a warning:

system2("command", args = c("-v", executable), stdout = FALSE)
# Error in paste(c(env, shQuote(command), args), collapse = " ") :
#   object 'executable' not found

To suppress this warning we can wrap the command system2() command in a suppressWarnings().

Finally, we should note that by default system() and system2() return the exit code of the invoked command, rather than the output of the command itself (as you might expect).

If the desired executable does exist on the system PATHA, our invocation of system2("command") will return with an exit code of 0. Hence we can convert the exit code to a Boolean representing whether the executable exists on the system PATH as:

exit_code = suppressWarnings(system2("command", args = c("-v", bin)))
bin_on_path = exit_code == 0

Wrapping this up into something reusable we arrive at the function:

is_bin_on_path = function(bin) {
  exit_code = suppressWarnings(system2("command", args = c("-v", bin), stdout = FALSE))
  return(exit_code == 0)
}

Other notes

The more modern replacement of system2(), processx(), at least in my experience, seems unhappy calling command. I'm not sure why this is the case.

Upvotes: 1

Kota Mori
Kota Mori

Reputation: 6740

If it is a command in PATH, then it is actually a file somewhere in the search path.

An easy way is

system("which <command>")  # for unix
system("where <command>")  # for windows

If the command exists, then this should show the full path. Otherwise nothing.

Upvotes: 1

Related Questions