Whitespace in bash path with java

半城伤御伤魂 提交于 2020-01-03 03:15:11

问题


So, I try to export file variable:

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

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

And I get some exception on this line:

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

P.S. If I try "prepend space in file name with \", I get:

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

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

And I also get some exception on this line:

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

P.P.S If I wrap path in "", I also get exception like above


回答1:


Add: mostly dupe Why does Runtime.exec(String) work for some but not all commands?

Runtime.exec is not a shell

  1. The overloads of Runtime.exec that take a String tokenize at whitespace. Period. A shell tokenizes at whitespace by default but this can be overridden with quotes or backslash; in Runtime.exec it cannot. If you want any other tokenization you have to use the overloads that take String[] instead. This answers the question you actually asked. For example you could do the equivalent of open 'path with spaces' by:
    Process p = runtime.exec (new String[] {"open", "path with spaces"});
  1. Runtime.exec runs programs only. Shell commands often run a program but not always. export is a shell builtin that the shell executes but is not a program so Runtime.exec cannot.

  2. Runtime.exec runs programs in child processes, which is like a shell. Even if you could somehow run export as a child process, the change it makes would exist only in that child process. It would NOT affect the Java process or any other programs run from the Java process, just like if you use shell to do export in a child process -- most simply a subshell using parentheses like ( export foo=bar; echo $foo ); echo $foo -- then it is set only in the child shell process and not the parent shell, and not any other children of the parent shell.

Thus if your goal is to set an environment variable to be used by some other program(s), you cannot do that by running anything in Runtime.exec. You can pass an environment that is modified to add (or change or delete) environment variables to some other (real) program you run with Runtime.exec by using the overloads that take an envp parameter -- see the javadoc -- or with ProcessBuilder by using the environment() method (javadoc)

But if your goal is to do the equivalent of shell's foo='path with spaces'; open "$foo" (note quotes are needed for this to work in shell) you can't. The substitution of $foo to path with spaces (within a token, and thus passed as an argument) is done by the shell not by the open program -- and Runtime.exec is not a shell so it doesn't do this. You have to pass the path with spaces token/argument yourself as in point 1 above, or explicitly run a shell (commonly /bin/sh or just sh) and give the shell the foo=...; ...$foo... commands to execute -- and export isn't needed since the variable is used only in the shell not the child process.

BTW even in shell you don't use a $ when you set an environment variable or shell variable, only when you use the value of a variable (or of certain other things like a command substitution or arithmetic expression).



来源:https://stackoverflow.com/questions/48425729/whitespace-in-bash-path-with-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!