Linux/Mac下Java调用7-Zip压缩文件夹权限问题解决问询
问题:Linux/Mac系统下调用7-Zip可执行文件提示Permission denied无法完成压缩
我编写了Java函数从src/main/resources目录加载7-Zip可执行文件到临时文件执行,用于压缩文件夹(Java自带7Z算法无法满足需求)。该代码在Windows系统正常运行,但Linux和Mac系统中,手动执行生成的临时文件时提示Permission denied,更换临时文件路径也无法解决,请问如何修复?
相关代码
核心执行函数
public static void runExecutable(String filePath, String command, boolean commandLine, boolean wait) { InputStream inputStream = CommonMethods.class.getClassLoader().getResourceAsStream(filePath); String tempFileSuffix = ""; switch (CommonMethods.getOperatingSystem()) { case "Windows": tempFileSuffix = ".exe"; break; case "Linux": case "Mac": tempFileSuffix = ".bin"; break; } File tempFile; try { tempFile = File.createTempFile("AutoFPCurator", tempFileSuffix); } catch (IOException e) { new ErrorDialog(e); return; } try (FileOutputStream outputStream = new FileOutputStream(tempFile)) { byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } outputStream.close(); } catch (IOException e) { new ErrorDialog(e); return; } String cmdProgram = ""; String cFlag = "-c"; switch (CommonMethods.getOperatingSystem()) { case "Windows": cmdProgram = "cmd.exe"; cFlag = "/c"; break; case "Mac": cmdProgram = "sh"; break; case "Linux": cmdProgram = "bash"; break; default: return; } ProcessBuilder processBuilder = !commandLine ? new ProcessBuilder(tempFile.getAbsolutePath(), command) : new ProcessBuilder(cmdProgram, cFlag, tempFile.getAbsolutePath(), command); processBuilder.redirectErrorStream(true); Process process; try { process = processBuilder.start(); } catch (IOException e) { new ErrorDialog(e); return; } if (!wait) { return; } try { process.waitFor(); } catch (InterruptedException e) { new ErrorDialog(e); } }
调用代码
switch (CommonMethods.getOperatingSystem()) { case "Windows": exeString = "programs/7zip/7za.exe"; break; case "Mac": exeString = "programs/7zip/7zzmac"; break; case "Linux": exeString = "programs/7zip/7zznux"; break; default: System.out.println(commonStrs.get("unsupportedOS")); return; } CommonMethods.runExecutable(exeString, args, true, true);
解决方案
核心原因
Linux和Mac系统中,从资源文件写出的临时文件默认没有可执行权限,这是导致Permission denied的直接原因(Windows系统不依赖文件可执行权限所以正常运行)。
修复步骤
在临时文件写出完成后,添加代码为Linux/Mac系统的临时文件赋予可执行权限:
方式一:快速设置所有用户可执行权限
在第二个try-catch块(文件写出操作)结束后,插入以下代码:
// 仅为非Windows系统添加可执行权限 if (!CommonMethods.getOperatingSystem().equals("Windows")) { tempFile.setExecutable(true, false); // 参数false表示所有用户都拥有可执行权限 }
方式二:精细控制POSIX权限(可选)
如果需要更精准的权限控制,可以使用Files.setPosixFilePermissions:
import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermission; import java.util.HashSet; import java.util.Set; // ... if (!CommonMethods.getOperatingSystem().equals("Windows")) { Set<PosixFilePermission> perms = new HashSet<>(); // 设置所有者可读、可写、可执行 perms.add(PosixFilePermission.OWNER_READ); perms.add(PosixFilePermission.OWNER_WRITE); perms.add(PosixFilePermission.OWNER_EXECUTE); // 设置同组用户可读、可执行 perms.add(PosixFilePermission.GROUP_READ); perms.add(PosixFilePermission.GROUP_EXECUTE); // 设置其他用户可读、可执行 perms.add(PosixFilePermission.OTHERS_READ); perms.add(PosixFilePermission.OTHERS_EXECUTE); Files.setPosixFilePermissions(tempFile.toPath(), perms); }
额外优化建议
- 临时文件使用完毕后,建议删除避免占用磁盘,可在
process.waitFor()之后添加:tempFile.delete(); // 立即删除 // 或者程序退出时自动删除 tempFile.deleteOnExit(); - 确保资源文件路径大小写与实际文件一致:Linux/Mac系统区分文件路径大小写,Windows不区分,避免因路径大小写问题导致资源加载失败。
内容的提问来源于stack exchange,提问作者user15881569
相关产品推荐
相关产品推荐

