Home > Software engineering >  ProcessBuilder("command","-v","date").start() fails with IOException:
ProcessBuilder("command","-v","date").start() fails with IOException:

Time:12-27

I am trying to find out whether a command exists (eg. date) using the command shell builtin, on Ubuntu. However the following (scroll further below for java snippet)

//main.kt
fun main(){
      val proc=ProcessBuilder("command","-v","date").start() //line 37
}

fails to run with stack trace

Exception in thread "main" java.io.IOException: Cannot run program "command": error=2, No such file or directory
    at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
    at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
    at MainKt.main(main.kt:37)
    at MainKt.main(main.kt)
Caused by: java.io.IOException: error=2, No such file or directory
    at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
    at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
    at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
    at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)
    ... 3 more

command is definitely available on my bash -

user@pc:~$ type command
command is a shell builtin

Why does the error occur?

Note that most other similar queries (there are plenty on SO) got solved via syntactic corrections or bad file paths, and don't apply here.

Env:
JDK 17 on Ubuntu 20.04.5 LTS

Java code:

import java.io.IOException;
//rough.java
public class rough {
    public static void main(String[] args) throws IOException {
        new ProcessBuilder("command","-v","date").start();
    }
}

CodePudding user response:

Your first sentence already has the solution:

[…] using the command shell builtin […]

ProcessBuilder execs processes directly and does not invoke a shell. And since a shell-builtin is a functionality provided by the shell and not a binary, it cannot be invoked (directly) with ProcessBuilder.

If you want to run a shell, you need to do so explicitly:

new ProcessBuilder("sh", "-c", "command -v date").start();
  • Related