如何通过使用Java的Windows / cygwin执行unix命令

我正试图完成两件事情:

  1. 我在Windows7上运行cygwin来执行我的UNIX命令,我需要通过编写一个Java应用程序来自动执行这个过程。 我已经知道如何通过Java使用'Process class'和Runtime.getRuntime().exec("cmd /c dir")来使用windows shell。 我需要能够用unix命令做同样的事情,例如: ls -la等等。 我应该看什么?

  2. 有没有办法记住一个shell的状态? 解释:当我使用: Runtime.getRuntime().exec("cmd /c dir") ,我总是得到我的主目录的列表。 如果我做了Runtime.getRuntime().exec("cmd /c cd <some-folder>") ,然后再执行Runtime.getRuntime().exec("cmd /c dir") ,我仍然会得到我的家庭文件夹。 有没有办法让程序记住它的状态,就像普通的shell一样?


看来Paŭlo提出的bash命令行不起作用:

 C:\cygwin\bin>bash -c ls -la -la: ls: command not found 

我很难搞清楚技术问题。

这是我的代码:

 p = Runtime.getRuntime().exec("C:\\cygwin\\bin\\bash.exe -c ls -la"); reader2 = new BufferedReader(new InputStreamReader(p.getInputStream())); line = reader2.readLine(); 

line结束了一个空值。


我将这添加到我的.bash_profile:

 #BASH export BASH_HOME=/cygdrive/c/cygwin export PATH=$BASH_HOME/bin:$PATH 

我还添加了以下内容:

系统属性 – >高级 – >环境variables – >用户variebales – >variables: BASH ,值: c:\cygwin\bin

依然没有…

但是,如果我执行此代替,它的工作原理!

 p = Runtime.getRuntime().exec("c:\\cygwin\\bin\\ls -la ~/\"Eclipse_Workspace/RenameScript/files copy\""); 

1.调用unix命令:

你只需要调用你的unix shell(比如用cygwin交付的bash)而不是cmd

 bash -c "ls -la" 

应该做。 当然,如果你的命令是一个外部程序,你可以直接调用它:

 ls -la 

当从Java开始时,最好使用带有字符串数组的变体,因为您没有让Java分析它来查看参数开始和结束的位置:

 Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe", "-c", "ls -la"}, new String[]{"PATH=/cygdrive/c/cygwin/bin"}); 

你的例子中的错误信息( ls: command not found )似乎表明你的bash找不到ls命令。 也许你需要把它放到PATH变量中(参见上面的Java方法)。

也许不是/cygdrive/c/cygwin/bin ,正确的目录名称是/usr/bin

(因为必须在Unix和Windows协议之间进行桥接,所以一切都变得复杂了。)

简单的ls命令可以这样调用:

 Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\ls.exe", "-la"}); 

2.调用多个命令:

基本上有两种在一个shell中调用多个命令的方法:

  • 一次把它们全部传给壳; 要么
  • 将它们交互地传递给shell。

对于第一种方法,只需将多个命令作为参数传递给-c选项, 或\n (换行符),如下所示:

 bash -c "cd /bin/ ; ls -la" 

或从Java(适应上面的例子):

 Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe", "-c", "cd /bin/; ls -la"}, new String[]{"PATH=/cygdrive/c/cygwin/bin"}); 

在这里,shell将解析命令行,并将其作为脚本执行。 如果它包含多个命令,它们将被全部执行,如果shell由于某种原因(如exit命令)之前不以某种方式退出。 (我不确定Windows cmd是否能以类似的方式工作,请测试并报告。)

命令行上的命令不是通过bash(或cmd或任何你正在使用的shell),而是通过Process的输入流传递它们。

  • 以“输入模式”启动的shell(例如,既没有-c选项也没有shell脚本文件参数的shell)将从流中读取输入,并将第一行解释为命令(或多个命令)。
  • 然后它会执行这个命令。 如果需要,命令本身可能会从流中读取更多输入。
  • 然后,shell将读取下一行,将其解释为命令,然后执行。
  • (在某些情况下,shell必须读取多行,例如对于长字符串或组合命令(如if或loop)。
  • 这将继续下去,直到流的结束(例如stream.close()在你身边)或执行一个显式的exit命令(或其他一些exit命令)。

这将是一个例子:

 Process p = Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe", "-s"}); InputStream outStream = p.getInputStream(); // normal output of the shell InputStream errStream = p.getInputStream(); // error output of the shell // TODO: start separate threads to read these streams PrintStream ps = new PrintStream(p.getOutputStream()); ps.println("cd /bin/"); ps.println("ls -la"); ps.println("exit"); ps.close(); 

这里你不需要cygwin。 有几个纯Java库实现SSH协议。 使用它们。 顺便他们会解决你的第二个问题。 您将打开会话并执行相同会话的命令,因此shell状态将自动保留。

JSch就是一个例子。