如何使用FileUtils.copyDirectory跳过目标目录已存在文件,避免覆盖?
实现方案
方案1:自定义遍历逻辑(兼容所有Commons IO版本,灵活可控)
不用原生的copyDirectory批量复制,自己遍历源目录下的所有符合过滤规则的文件,逐个判断目标路径是否存在,仅在不存在时执行复制:
import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.IOFileFilter; import java.io.File; import java.io.IOException; import java.util.Collection; public void copyDirectorySkipExisting(File sourceDir, File destDir, IOFileFilter fileFilter) throws IOException { // 校验源目录合法性 if (!sourceDir.isDirectory()) { throw new IllegalArgumentException("源路径不是有效目录: " + sourceDir); } // 目标目录不存在则先创建 FileUtils.forceMkdir(destDir); // 递归获取源目录下所有符合过滤规则的文件 Collection<File> sourceFiles = FileUtils.listFiles(sourceDir, fileFilter, IOFileFilter.TrueFileFilter.TRUE); for (File sourceFile : sourceFiles) { // 计算对应目标文件的相对路径,自动适配不同系统的路径分隔符 String relativePath = sourceDir.toURI().relativize(sourceFile.toURI()).getPath(); File destFile = new File(destDir, relativePath); // 仅目标文件不存在时执行复制 if (!destFile.exists()) { // 提前创建目标文件的父目录,避免路径不存在报错 FileUtils.forceMkdirParent(destFile); FileUtils.copyFile(sourceFile, destFile); } } }
调用时直接替换原有copyDirectory逻辑即可:copyDirectorySkipExisting(sourceDir, destinationDir, fileFilter);
方案2:使用Commons IO 2.8+ 内置配置实现
如果你使用的Apache Commons IO版本 >= 2.8.0,可以直接通过配置复制选项指定文件存在时的处理策略为跳过,不需要自己写遍历逻辑:
import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; import java.io.File; import java.io.IOException; import java.nio.file.CopyOption; import java.nio.file.StandardCopyOption; // 配置复制规则:文件已存在时直接跳过 CopyOption[] copyOptions = new CopyOption[]{StandardCopyOption.SKIP_EXISTING}; // 第四个参数为目录过滤规则,无特殊需求传TrueFileFilter.INSTANCE即可保留完整目录结构 FileUtils.copyDirectory(sourceDir, destinationDir, fileFilter, TrueFileFilter.INSTANCE, copyOptions);
可选优化
如果需要同时保留源文件的修改时间、权限等属性,可以在复制选项中增加StandardCopyOption.COPY_ATTRIBUTES。
内容的提问来源于stack exchange,提问作者rizzanasking
相关产品推荐
相关产品推荐

