Java调用含空格的Bash路径报错问题求助
我来帮你搞定这个问题——Java里用Runtime.exec()处理带空格的Bash路径确实容易踩坑,主要是因为它的参数解析逻辑和我们平时用shell的不一样。先给你分析下你之前的尝试为什么失败,再给你正确的做法:
为什么你的尝试都失败了?
第一种尝试(变量赋值):
runtime.exec(String.format("$MY_FILEPATH=\"%s\"", somePath))
默认情况下Runtime.exec()不会启动shell来解析命令,它会把整个字符串当作要执行的程序名。所以它会尝试找名为$MY_FILEPATH="/Users/me/File的程序,自然会报“找不到文件或目录”的错误。第二种尝试(反斜杠转义):
runtime.exec(String.format("open %s", somePath))exec()不会像shell那样处理反斜杠转义,它会把File\直接当作文件名的一部分传递给open命令,导致命令寻找的是File\、with\这些不存在的文件。第三种尝试(引号包裹):同样的问题,
exec()不会解析引号,它会把引号当作路径的一部分传递给命令,比如实际传给open的是"/Users/me/File with whitespaces.json"(带引号),系统自然找不到这个文件。
正确的解决方案
方案1:使用exec()的数组参数版本(推荐)
Runtime.exec()提供了接收字符串数组的重载方法,这个方法会直接把数组的每个元素作为命令的一个参数,不会按空格分割,完美解决空格问题:
String somePath = "/Users/me/File with whitespaces.json"; Runtime runtime = Runtime.getRuntime(); // 数组第一个元素是命令,后面依次是参数 Process process = runtime.exec(new String[]{"open", somePath});
方案2:如果需要执行shell命令(比如变量赋值、管道)
如果你的场景必须用shell解析命令(比如设置环境变量、执行复杂脚本),需要显式调用bash -c,并且把整个shell命令作为一个参数传递:
String somePath = "/Users/me/File with whitespaces.json"; Runtime runtime = Runtime.getRuntime(); // 用bash -c启动shell,把完整命令作为单个参数传入 Process process = runtime.exec(new String[]{ "bash", "-c", String.format("MY_FILEPATH=\"%s\"; echo $MY_FILEPATH", somePath) });
额外推荐:使用ProcessBuilder替代Runtime.exec()
ProcessBuilder是Java 5+引入的,比Runtime.exec()更灵活易用,同样支持数组参数,还能设置工作目录、环境变量等:
// 执行open命令打开文件 String somePath = "/Users/me/File with whitespaces.json"; ProcessBuilder pb = new ProcessBuilder("open", somePath); Process process = pb.start(); // 执行shell命令的场景 ProcessBuilder shellPb = new ProcessBuilder( "bash", "-c", String.format("MY_FILEPATH=\"%s\"; cat $MY_FILEPATH", somePath) ); Process shellProcess = shellPb.start();
这样处理后,带空格的路径就能被正确识别啦~
内容的提问来源于stack exchange,提问作者Hasdfa

