1

So guys I want to execute a command that you can execute on the cmd in my Java program. After doing some study, I thought i found a way to do this. However, my code doesn't work.

My code is

import java.io.*;

public class CmdTest {
    public static void main(String[] args) throws Exception {
        String[] command = {"ag","startTimes conf.js >> pro.txt"};
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.directory(new File("./test-java/"));
        Process p = builder.start();
    }
}

The program executes but produces no output. I tried using other commands like "ls -a", but still no output.

Can someone please help me debug this or suggest a better way of doing this? Thank you

Edit 1: I am executing this on a Mac. If that is necessary for debugging

Edit 2: The usual ls and other commands are working with the solutions that you guys have provided. I however want to use the ag (the_silver_searcher) command in the Java program. When i try that, i get the following error -

Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory 
Sid
  • 103
  • 1
  • 2
  • 12

5 Answers5

1

While there is ProcessBuilder, I've always used Runtime.getRuntime().exec("cmd");

Process Runtime.exec(String)

It returns a Process which you can get the input and output streams of

Even if you stay with the ProcessBuilder, you should still have access to the Process.get<Input/Output/Error>Stream()

phflack
  • 2,729
  • 1
  • 9
  • 21
  • I get error - "Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory". What do you suggest i do? – Sid Oct 13 '17 at 17:56
  • @Sid try putting in the full filepath, it's probably running the command from the local directory – phflack Oct 13 '17 at 18:09
1

The existing answers give you the information on how to solve your problem in code, but they don't give a reason why your code is not working.

When you execute a program on a shell, there's significant processing done by the shell, before the program is ever executed. Your command line

    String[] command = {"ag","startTimes conf.js >> pro.txt"};
    ProcessBuilder builder = new ProcessBuilder(command);

assumes that the command ag is run with the single argument startTimes conf.js >> pro.txt - most likely not what you want to do. Let's go one step further: What if you wrote

    String[] command = {"ag","startTimes", "conf.js", ">>", "pro.txt"};
    ProcessBuilder builder = new ProcessBuilder(command);

?

This would assume that the ag command knows about the >> parameter to redirect its output - and here is where the shell comes into play: The >> operator is an instruction to the shell, telling it what to do with the output from stdout of the process. The process ag, when started by the shell, never has an idea of this redirection and has no clue about >> and the target file name at all.

With this information, just use the code samples from any of the other answers. I won't copy them into mine for proper attribution.

Olaf Kock
  • 46,930
  • 8
  • 59
  • 90
  • thank you so much Olaf, your inputs really helped. i was finally able to solve the problem – Sid Oct 19 '17 at 08:10
0

You need to read the output of the process by opening an input stream from the process:

try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())) {
    System.out.println(reader.readLine()); // process the output stream somehow
}

Additionally you might the read the error stream ( p.getErrorStream()), which I often have done in a separate stream, in Java 8 you can use redirectErrorStream(true) on the ProcessBuilder to automatically add the error stream to the input stream. Of course you can't distinquish anymore from which stream the input comes, but it makes reading easier. If you don't read the input or error stream and the process's buffer becomes full the processes tend to pause until there is enough room in the buffer again.

M. le Rutte
  • 3,525
  • 3
  • 18
  • 31
  • I get error - "Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory". What do you suggest i do? – Sid Oct 13 '17 at 17:56
0

You can also add

builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);

before the start method which redirects the output to the console.

  • Hey ben, your solution works when i use commands like ls. But when i use the ag command, i get the error - Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory – Sid Oct 13 '17 at 17:39
  • What can i do now? – Sid Oct 13 '17 at 17:39
  • 1
    You are asking a new question. It would be fair to accept one of the two solutions provided to you and maybe post a new SO question. – M. le Rutte Oct 13 '17 at 18:09
0
//"ls" command runs under the "sh" on linux(cmd.exe on windows), so first arg is "sh"    
//second arg "-c" tells "sh" which exact command should be executed
//"ls" is actual command
//"startTimes" as I understand is a file or directory, it is arg for "ls" command
//"conf.js" is second arg for "ls" command
new ProcessBuilder("sh", "-c", "ls", "startTimes", "conf.js")
//set working dir for "sh" process"
            .directory(new File("./test-java/"))
//output will be written to "pro.txt" in working dir of "sh" process
            .redirectOutput(new File("./test-java/pro.txt"))
            .start();
Dmitry
  • 87
  • 4
  • 1
    Please review [How do I write a good answer](https://stackoverflow.com/help/how-to-answer). Code-only answers are discouraged because they do not explain how they resolve the issue in the question. You should update your answer to explain what this does and how it solves the problem. – FluffyKitten Oct 14 '17 at 01:26