Java使用ProcessBuilder执行ls -l报错找不到文件或目录如何解决
问题根因
报错和目录权限/存在性无直接关联,核心是ProcessBuilder的传参逻辑不符合预期:ProcessBuilder不会自动拆分单字符串内的命令和参数,你传入"ls -l"时,JVM会直接查找文件名完全匹配ls -l的可执行文件,系统中不存在这个命名的程序,因此抛出error=2, No such file or directory错误——你可以直接看报错信息里的描述Cannot run program "ls -l",已经明确说明被识别为程序名的是ls -l而非ls。
可直接运行的修正代码
import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; public class LsTest { public static void main(String[] args) throws Exception { // 命令和每个参数单独作为构造参数传入,不要拼接在同一个字符串中 ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l"); File targetDir = new File("/home/minecraft/paper/event"); // 提前校验目录合法性,避免目录本身问题触发报错 if (!targetDir.exists() || !targetDir.isDirectory()) { throw new RuntimeException("目标路径不存在或不是有效目录: " + targetDir.getAbsolutePath()); } processBuilder.directory(targetDir); // 合并标准错误和标准输出,避免单独读取两个流的死锁问题 processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); // 读取命令执行输出 try (BufferedReader br = new BufferedReader( new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } // 等待命令执行完成,获取退出码 int exitCode = process.waitFor(); System.out.println("命令执行结束,退出码: " + exitCode); } }
常见踩坑说明
- 如果你使用
Runtime.getRuntime().exec()实现同类功能,同样不要传入拼接完成的单字符串命令,必须使用字符串数组传参,格式为exec(new String[]{"命令", "参数1", "参数2"}) - 如果需要执行shell内置命令(比如管道、重定向逻辑、Windows下的
dir命令),不能直接调用命令本身,需要显式唤起系统shell:- Linux/macOS环境:
new ProcessBuilder("bash", "-c", "你的完整命令串") - Windows环境:
new ProcessBuilder("cmd.exe", "/c", "你的完整命令串")
- Linux/macOS环境:
- 启动外部进程后必须及时读取输出流、调用
waitFor()等待进程退出,否则会因为输出缓冲区占满导致进程永久僵死。
内容的提问来源于stack exchange,提问作者flavianthepavian
相关产品推荐
相关产品推荐

