44

I am trying to execute command line arguments via Java. For example:

// Execute command
String command = "cmd /c start cmd.exe";
Process child = Runtime.getRuntime().exec(command);

// Get output stream to write from it
OutputStream out = child.getOutputStream();

out.write("cd C:/ /r/n".getBytes());
out.flush();
out.write("dir /r/n".getBytes());
out.close();

The above opens the command line but does not execute cd or dir. Any ideas? I am running Windows XP, JRE6.

(I have revised my question to be more specific. The following answers were helpful but do not answer my question.)

Madhawa Priyashantha
  • 9,633
  • 7
  • 33
  • 60
joe
  • 16,988
  • 36
  • 94
  • 131
  • joe, if you still feel that your question hasn't been answered I think you should provide more background. My answer definitely does what you want to achieve, which is to list the files in C:\. Vincent and Carles' answers show you how to run multiple shell commands from a single `exec()` call. I'm not sure what you're not satisfied with at this point. – Andrzej Doyle Nov 12 '10 at 10:29

11 Answers11

68

I found this in forums.oracle.com

Allows the reuse of a process to execute multiple commands in Windows: http://kr.forums.oracle.com/forums/thread.jspa?messageID=9250051

You need something like

   String[] command =
    {
        "cmd",
    };
    Process p = Runtime.getRuntime().exec(command);
    new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
    new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
    PrintWriter stdin = new PrintWriter(p.getOutputStream());
    stdin.println("dir c:\\ /A /Q");
    // write any other commands you want here
    stdin.close();
    int returnCode = p.waitFor();
    System.out.println("Return code = " + returnCode);

SyncPipe Class:

class SyncPipe implements Runnable
{
public SyncPipe(InputStream istrm, OutputStream ostrm) {
      istrm_ = istrm;
      ostrm_ = ostrm;
  }
  public void run() {
      try
      {
          final byte[] buffer = new byte[1024];
          for (int length = 0; (length = istrm_.read(buffer)) != -1; )
          {
              ostrm_.write(buffer, 0, length);
          }
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
  }
  private final OutputStream ostrm_;
  private final InputStream istrm_;
}
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
Pepe
  • 681
  • 5
  • 2
  • 4
    Great that the link is invalid but codes copied here are enough. – mrmoment Jun 23 '14 at 04:17
  • @tvanfosson Hi, I have one doubt! It works for 'cmd', I am unable to use this for 'powershell'. Is there any workaround that I could follow ? – GP cyborg Oct 27 '14 at 09:06
17

If you want to run several commands in the cmd shell then you can construct a single command like this:

  rt.exec("cmd /c start cmd.exe /K \"cd c:/ && dir\"");

This page explains more.

Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192
5

Every execution of exec spawns a new process with its own environment. So your second invocation is not connected to the first in any way. It will just change its own working directory and then exit (i.e. it's effectively a no-op).

If you want to compose requests, you'll need to do this within a single call to exec. Bash allows multiple commands to be specified on a single line if they're separated by semicolons; Windows CMD may allow the same, and if not there's always batch scripts.

As Piotr says, if this example is actually what you're trying to achieve, you can perform the same thing much more efficiently, effectively and platform-safely with the following:

String[] filenames = new java.io.File("C:/").list();
Community
  • 1
  • 1
Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
2

Try this link

You do not use "cd" to change the directory from which to run your commands. You need the full path of the executable you want to run.

Also, listing the contents of a directory is easier to do with the File/Directory classes

Piotr
  • 4,813
  • 7
  • 35
  • 46
2

The code you posted starts three different processes each with it's own command. To open a command prompt and then run a command try the following (never tried it myself):

try {
    // Execute command
    String command = "cmd /c start cmd.exe";
    Process child = Runtime.getRuntime().exec(command);

    // Get output stream to write from it
    OutputStream out = child.getOutputStream();

    out.write("cd C:/ /r/n".getBytes());
    out.flush();
    out.write("dir /r/n".getBytes());
    out.close();
} catch (IOException e) {
}
TooCool
  • 10,598
  • 15
  • 60
  • 85
Peter Knego
  • 79,991
  • 11
  • 123
  • 154
1

Each of your exec calls creates a process. You second and third calls do not run in the same shell process you create in the first one. Try putting all commands in a bat script and running it in one call: rt.exec("cmd myfile.bat"); or similar

Carles Barrobés
  • 11,608
  • 5
  • 46
  • 60
0

As i also faced the same problem and because some people here commented that the solution wasn't working for them, here's the link to the post where a working solution has been found.

https://stackoverflow.com/a/24406721/3751590

Also see the "Update" in the best answer for using Cygwin terminal

Community
  • 1
  • 1
singe3
  • 2,065
  • 4
  • 30
  • 48
0

This because every runtime.exec(..) returns a Process class that should be used after the execution instead that invoking other commands by the Runtime class

If you look at Process doc you will see that you can use

  • getInputStream()
  • getOutputStream()

on which you should work by sending the successive commands and retrieving the output..

Jack
  • 131,802
  • 30
  • 241
  • 343
0

Writing to the out stream from the process is the wrong direction. 'out' in that case means from the process to you. Try getting/writing to the input stream for the process and reading from the output stream to see the results.

Kelly S. French
  • 12,198
  • 10
  • 63
  • 93
0
try {
    String command = "Command here";
    Runtime.getRuntime().exec("cmd /c start cmd.exe /K " + command);
} catch (IOException e) {
    e.printStackTrace();
}
Michael
  • 3,093
  • 7
  • 39
  • 83
0

Here is a simpler example that does not require multiple threads:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class SimplePty
{
    public SimplePty(Process process) throws IOException
    {
        while (process.isAlive())
        {
            sync(process.getErrorStream(), System.err);
            sync(process.getInputStream(), System.out);
            sync(System.in, process.getOutputStream());
        }
    }
    
    private void sync(InputStream in, OutputStream out) throws IOException
    {
        while (in.available() > 0)
        {
            out.write(in.read());
            out.flush();
        }
    }
    
    public static void main( String[] args ) throws IOException
    {
        String os = System.getProperty("os.name").toLowerCase();
        String shell = os.contains("win") ? "cmd" : "bash";
        Process process = new ProcessBuilder(shell).start();
        new SimplePty(process);
    }
}
egerardus
  • 11,316
  • 12
  • 80
  • 123