【问题标题】:java using shell commandsjava使用shell命令
【发布时间】:2021-03-02 08:43:52
【问题描述】:

因此尝试使用“cp”将文件从一个位置复制到另一个位置 - 该文件以包含空格的文件名命名(“test test”)。在 shell(bash)中调用命令时它工作正常,但从 java 调用它失败。我使用转义字符。代码:

import java.io.*;

public class Test {

  private static String shellify(String path) {
    String ret = path;
    System.out.println("shellify got: " + ret);
    ret = ret.replace​(" ", "\\ ");
    System.out.println("shellify returns: " + ret);
    return ret;
  }    

  private static boolean copy(String source, String target) {
    String the_command = ""; // will be global later
    boolean ret = false;
    try {
      Runtime rt = Runtime.getRuntime();
      String source_sh = shellify(source);
      String target_sh = shellify(target);
      the_command = new String
    ("cp -vf " + source_sh + " " + target_sh);
      System.out.println("copy execing: " + the_command);
      Process p = rt.exec(the_command);
      InputStream is = p.getInputStream();
      BufferedReader br = new BufferedReader
    (new InputStreamReader(is));
      String reply = br.readLine();
      System.out.println("Outcome; " + reply);
      ret = (reply != null) && reply.contains("->");
    } catch(Exception e) {
      System.out.println(e.getMessage());
    }
    the_command = "";
    return ret;
  }

  public static void main(String[] args) {
    String source = "test1/test test";
    String target = "test2/test test";
    if(copy(source, target))
      System.out.println("Copy was successful");
    else
      System.out.println("Copy failed");
  }

}

...结果是这样的

shellify got: test1/test test
shellify returns: test1/test\ test
shellify got: test2/test test
shellify returns: test2/test\ test
copy execing: cp -vf test1/test\ test test2/test\ test
Outcome; null
Copy failed

而如果我使用 bash 复制成功(大惊喜)。

Sino-Logic-IV:bildbackup dr_xemacs$ cp -vf test1/test\ test test2/test\ test
test1/test test -> test2/test test

谁能告诉我这是为什么?复制没有空格的文件就可以了。

/dr_xemacs

【问题讨论】:

  • 很确定 Runtime 不知道 ` - have you tried using the exec` 方法,该方法采用字符串数组作为命令(exec(一个字符串)的文档:"...使用 StringTokenizer 将命令字符串分解为标记..." - 标记器仅使用 " \t\n\r\f" 分隔标记,`` 只是它的 普通 字符)
  • 试试String[] command = { "cp", "-vf ", source_sh, target_sh }; 之类的东西(注意:new String(text) 基本上不需要)(注2:我认为反斜杠、引号和类似的解释是由shell line reader 完成的,这不是由Runtime)

标签: java shell cp


【解决方案1】:

您应该单独传递参数,并且它们不需要在 shellify 中转义,因为 exec 的 String[] 版本将每个参数作为一个参数单独提供给脚本,即使它们包含空格:

String[]the_command = new String[] {"cp","-vf", source, target);

如果cp 不在某个PATH 目录中,您可能需要修复Java VM 可用的PATH,或者您可以完全限定the_command [0] 中可执行cp 的路径。

您的代码缺少检查cp / 进程退出代码的行,在使用STDOUT / getInputStream() 后添加waitFor

int rc = p.waitFor();

【讨论】:

  • 是的。 exec 不理解 shell 转义和 shell 引用,如果您尝试执行使用它们的命令字符串,将会搞砸。
猜你喜欢
  • 2015-04-04
  • 2017-04-11
  • 2011-01-28
  • 2011-03-04
  • 1970-01-01
  • 2015-03-23
  • 2010-11-27
  • 1970-01-01
相关资源
最近更新 更多