You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 22:43:22