用java在bash路径中的空格

时间:2018-01-24 15:10:37

标签: java bash command-line-interface whitespace

所以,我尝试导出文件变量:

String somePath = "/Users/me/File with whitespaces.json";
Runtime runtime = Runtime.getRuntime();

runtime.exec(String.format("$MY_FILEPATH=\"%s\"", somePath));

我在这一行得到了一些例外:

java.io.IOException: Cannot run program "$MY_FILEPATH=/Users/me/File": error=2, No such file or directory

P.S。 如果我尝试使用\"在文件名中添加空格,我得到:

String somePath = "/Users/me/File\ with\ whitespaces.json";
Runtime runtime = Runtime.getRuntime();

runtime.exec(String.format("open %s", somePath));

我也在这一行得到了一些例外:

The files /Users/me/File\, with\, whitespaces.json do not exist.

P.P.S 如果我在""中包装路径,我也会像上面那样得到例外

1 个答案:

答案 0 :(得分:1)

添加:主要是欺骗Why does Runtime.exec(String) work for some but not all commands?

Runtime.exec不是shell

  1. Runtime.exec在空白处采用String标记化的重载。期。默认情况下,shell会在空白处进行标记,但这可以用引号或反斜杠覆盖;在Runtime.exec它不能。如果您想要任何其他标记化,则必须使用String[]代替的重载。这回答了你实际问的问题。例如,您可以通过以下方式执行open 'path with spaces'的等效操作:
  2.     Process p = runtime.exec (new String[] {"open", "path with spaces"});
    
    1. Runtime.exec仅运行程序。 Shell命令经常运行程序,但并非总是如此。 export是shell内置的,shell执行但不是程序,因此Runtime.exec不能。

    2. Runtime.exec在子进程中运行程序, 就像shell一样。即使您可以以某种方式运行export作为子进程,它所做的更改将仅存在于该子进程中的 。它不会影响Java进程或从Java进程运行的任何其他程序,就像在子进程中使用shell进行export一样 - 大多数只是使用括号如( export foo=bar; echo $foo ); echo $foo的子shell - 然后它只在子shell进程中设置,而不是父shell,而不是父shell的任何其他子进程。

    3. 因此,如果您的目标是设置一个环境变量以供其他某些程序使用,则不能通过在{{1}中运行任何来实现这一点}。您可以通过使用带有Runtime.exec参数的重载来传递一个被修改的环境,以便将环境变量添加(或更改或删除)到您使用Runtime.exec运行的其他(实际)程序 - 请参阅{使用envp方法the javadoc

      {3}}或ProcessBuilder

      但是,如果您的目标是执行相同的shell environment()(需要注意引号才能在shell中工作),那么您就无法做到。将foo='path with spaces'; open "$foo"替换为$foo(在令牌中,因此作为参数传递)由shell 而不是path with spaces程序完成 - open不是shell,所以它不会这样做。您必须自己传递Runtime.exec令牌/参数,如上面第1点所述,或者显式运行shell(通常为path with spaces或仅/bin/sh)并提供 shell 要执行的sh命令 - 并且不需要foo=...; ...$foo...,因为变量仅用于shell而不是子进程。

      BTW即使在shell中,当你设置环境变量或shell变量时,你也不会使用export,只有当你使用值时一个变量(或某些其他东西,如命令替换或算术表达式)。