如何通过Java执行cmd命令

44

我正在尝试通过Java执行命令行参数。例如:

// 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();

上述代码打开了命令行但没有执行cddir。有任何想法吗?我正在运行Windows XP,JRE6。

(我已经修改了我的问题以使其更加具体。下面的答案虽然有用,但并未回答我的问题。)


Joe,如果你仍然觉得你的问题没有得到解答,我认为你应该提供更多的背景信息。我的回答肯定能够实现你想要达到的目的,也就是列出C盘中的文件。Vincent和Carles的回答向你展示了如何从单个exec()调用中运行多个shell命令。我不确定此时你还有什么不满意的地方。 - Andrzej Doyle
11个回答

68

我在forums.oracle.com上找到了这个。

允许在Windows中重复使用进程来执行多个命令:http://kr.forums.oracle.com/forums/thread.jspa?messageID=9250051

你需要像这样的东西:

   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);

同步管道类:

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_;
}

4
链接无效很好,但这里复制的代码已足够。 - mrmoment
@tvanfosson 你好,我有一个疑问!它适用于“cmd”,但我无法在“powershell”中使用它。是否有任何解决方法可以遵循? - GP cyborg

17
如果您想在cmd shell中运行多个命令,则可以构建一个这样的单个命令:
  rt.exec("cmd /c start cmd.exe /K \"cd c:/ && dir\"");

这个页面有更详细的解释。


5
每次执行 exec 都会生成一个新的进程,该进程有自己的环境。因此,第二次调用与第一次没有任何关联。它只会更改 自己的 工作目录,然后退出(即实际上是无操作)。
如果您想要组合请求,则需要在单个对 exec 的调用中执行此操作。如果它们由分号分隔,则 Bash 允许在单行上指定多个命令;Windows CMD 可能也允许相同的操作,如果不行,还有批处理脚本可用。
正如 Piotr 所说,如果这个例子实际上是您想要实现的内容,那么可以使用以下方式更有效、更可靠和跨平台:
String[] filenames = new java.io.File("C:/").list();

@Boris - 请查看问题历史记录,自我发布此答案以来已经进行了两个月的编辑。 - Andrzej Doyle

2

你发布的代码启动了三个不同的进程,每个进程都有自己的命令。如果要打开命令提示符并运行命令,请尝试以下方法(我自己从未尝试过):

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) {
}

4
谢谢。这会打开命令行,但不会执行cd或dir命令。 - joe
69
哎呀,我喜欢带有免责声明“从未尝试过”的代码片段。 >_< - arkon
4
这会打开命令行界面,但不会执行cd或dir命令,为什么? - Akhilesh Dhar Dubey
14
为什么它已经得到批准了...它是误报! - Pankaj Sejwal
1
我猜至少应该将 /n 改为 \n。但总体来说,执行命令和控制 shell 的方法相当可疑。 - eckes
4
以下答案包含实际答案。 - Mgamerz

2

请尝试这个链接

您不能使用“cd”来更改要运行命令的目录。您需要完整路径来运行想要的可执行文件。

此外,使用File/Directory类更容易列出目录中的内容。


答案与问题无关。 - Mert Serimer

1

你每次调用 exec 都会创建一个新进程。第二个和第三个调用不会在你第一个调用中创建的同一 shell 进程中运行。试着将所有命令放入一个批处理脚本中并在一个调用中运行它: rt.exec("cmd myfile.bat"); 或类似操作。


答案与问题的代码无关 - 没有“其他”exec调用。 - Boris Daich
2
曾经我已经回答了,但是问题在那之后被编辑过。在给这个问题点踩之前,请查看它的修订历史记录。 - Carles Barrobés

0

我也遇到了同样的问题,因为有些人在这里评论说解决方案对他们不起作用,所以这里提供一个已经找到的可行解决方案的链接。

https://dev59.com/8YDba4cB1Zd3GeqPKvP9#24406721

还可以查看最佳答案中有关使用Cygwin终端的“更新”。

0

这是因为每个 runtime.exec(..) 都会返回一个 Process 类,应该在执行后使用它,而不是通过 Runtime 类调用其他命令。

如果您查看 Process doc,您将看到可以使用以下内容:

  • getInputStream()
  • getOutputStream()

您应该通过发送连续的命令并检索输出来处理它们。


0

从进程中向输出流写入是错误的方向。在这种情况下,“out”表示从进程到您。尝试获取/写入进程的输入流并从输出流读取结果。


0
try {
    String command = "Command here";
    Runtime.getRuntime().exec("cmd /c start cmd.exe /K " + command);
} catch (IOException e) {
    e.printStackTrace();
}

1
请在您的答案中加入一些解释,以便其他人可以学习。 - Nico Haase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接