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

Apache Commons-IO 2.9+ Windows复制目录权限继承问题及解决咨询

Commons-IO 2.9+ Windows目录复制权限继承问题解决方法

在Windows系统中,使用commons-io@2.9及以上版本的FileUtils类调用FileUtils.copyDirectory(...)方法复制目录时,其行为与Windows默认复制行为存在差异。

默认情况下,对象会在创建或复制/移动到父文件夹时继承父对象的权限。唯一例外是在同一卷上将对象移动到不同文件夹时,会保留原权限。

预期行为:

  • 复制到目标位置的文件继承父目录权限

实际行为:

  • 复制到目标位置的文件不继承父目录权限

这一问题十分关键,因为Windows历来由系统管理权限,手动设置易引发更多错误,导致该方法无法满足Windows下的常见使用场景。


版本行为测试结果

经测试,这是一个行为退化问题,各版本表现如下:

版本状态
commons-io@1.1(2005)✅ 继承目标目录权限
commons-io@2.4(2013)✅ 继承目标目录权限
commons-io@2.5(2016)✅ 继承目标目录权限
commons-io@2.6(2017)✅ 继承目标目录权限
commons-io@2.7(2020)✅ 继承目标目录权限
commons-io@2.8(2020)✅ 继承目标目录权限
commons-io@2.9(2021)🚫 不继承目标目录权限
commons-io@2.10(2021)🚫 不继承目标目录权限
commons-io@2.11(2021)🚫 不继承目标目录权限

权限对比(以复制到C:\Program Files为例)

版本权限(icacls <file>)
commons-io@2.8NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Administrators:(I)(F)
BUILTIN\Users:(I)(RX)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(RX)
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(RX)
commons-io@2.9NT AUTHORITY\SYSTEM:(F)
BUILTIN\Administrators:(F)
WIN10ARM\owner:(F)

测试示例

示例代码:

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;

public class Main {
    private static final String PROGRAM_FILES = System.getenv().get("ProgramFiles");
    public static void main(String ... args) throws IOException {
        // 准备测试文件夹
        File folder = new File("MyApp");
        folder.mkdirs();
        File file = new File(folder, "test.txt");
        file.createNewFile();

        // 使用FileUtils复制目录
        File parent = new File(PROGRAM_FILES);
        File dest = new File(parent, "MyApp");
        System.out.println(String.format("创建目标父文件夹 %s...", dest));
        dest.mkdirs();
        System.out.println(String.format("复制内容从 %s 到 %s...", folder, dest));
        FileUtils.copyDirectory(folder, dest);

        // 测试权限可执行命令:
        //    icacls "%ProgramFiles%\MyApp\test.txt"
    }
}

编译代码:

javac -cp lib\commons-io-2.8.jar src\Main.java

运行代码(需以管理员身份打开CMD):

java -cp lib/commons-io-2.8.jar;src Main

测试权限:

icacls "%ProgramFiles%\MyApp\test.txt"

测试后手动删除%ProgramFiles%\MyApp,更换commons-io-2.9.0.jar重复测试即可对比差异。


不降级Commons-IO的解决方案

要恢复旧的权限继承行为,需自定义文件复制逻辑,让Windows系统自动处理权限继承,绕过Commons-IO 2.9+的权限复制逻辑:

  1. 实现自定义目录复制工具
    递归遍历源目录,创建目标目录时自动继承父权限,复制文件时不手动传递源文件权限,依赖Windows默认机制:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class WindowsFileCopyUtils {
    public static void copyDirectory(Path sourceDir, Path targetDir) throws IOException {
        Files.createDirectories(targetDir);
        
        Files.list(sourceDir).forEach(sourcePath -> {
            Path targetPath = targetDir.resolve(sourcePath.getFileName());
            try {
                if (Files.isDirectory(sourcePath)) {
                    copyDirectory(sourcePath, targetPath);
                } else {
                    Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
                }
            } catch (IOException e) {
                throw new RuntimeException("复制失败: " + sourcePath, e);
            }
        });
    }
}
  1. 替换原有调用
    将代码中FileUtils.copyDirectory(folder, dest)替换为:
WindowsFileCopyUtils.copyDirectory(folder.toPath(), dest.toPath());

这样就能让复制的文件自动继承目标父目录的权限,与Commons-IO 2.8及更早版本行为一致。


内容的提问来源于stack exchange,提问作者tresf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:24:52