Search code examples
javaterminalprocessbuilder

How do I run an installed terminal command in java?


I was recently writing a program that used ProcessBuilder to run terminal commands but whenever I run the program I get this error:

java.io.IOException: Cannot run program "convert": error=2, No such file or directory
    at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
    at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
    at Downloader.uncompressImage(Downloader.java:37)
    at Main.main(Main.java:51)
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:319)
    at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:250)
    at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1107)
    ... 3 more

I am pretty sure that this error is because it cannot find where the "convert" command is located because that is a command used by ImageMagick which I have installed on my computer. I know the command works because if I type in the command in the regular terminal window it works.

If the case is that the location for the "convert" command needs to be specified I still do not know where it is so if whoever answers this question could also tell me how to find that, that would be amazing.

In summary, I am pretty sure that the convert command is the one causing the error because it is a third party command, so my question is, how do I use the convert command without getting the error message, and if the solution requires me to find the directory of the convert command how do I do that?

If anyone wanted to see the code that is causing the error it is this:

public void uncompressImage (String name, boolean back, String path) {

        String b = "";  

        name = name.toLowerCase().replace("-", "").replace(" ", "").replace(".", "");

        if (back) {

            b = "-back";

        }

        ProcessBuilder pb = new ProcessBuilder();

        String[] args = new String[] {"convert" , name + b + ".gif", "-coalesce", name + b + ".gif"};

        try {
            pb.command("cd " + path);
            pb.command(args);
            Process process = pb.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

(This code is running on MacOS)

Edit: I have already tried checking path and name and both of those are correct.


Solution

  • Use ProcessBuilder.directory(File) instead of cd. Add inheritIO() to see what is going on. And remember to waitFor() your Process to complete. Like,

    try {
        pb.inheritIO();
        pb.directory(new File(path));
        pb.command(args);
        Process process = pb.start();
        process.waitFor();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    

    You may also need to change "convert" to "/usr/local/bin/convert" (depending on how and where you have it installed).