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

Java中实现同名目录合并的解决方案求助

合并同名目录结构的解决方案

场景说明

我有两个同名的content目录:

第一个目录结构:

| content
| - folderWithTextFile
| - - textFile.txt
| - - folderWithPdfFile
| - - - pdfFile.pdf

第二个目录结构:

| content
| - folderWithExeFile
| - - exeFile.exe
| - - folderWithPngFile
| - - - pngFile.png

需要合并为包含所有内容的content目录:

| content
| - folderWithTextFile
| - - textFile.txt
| - - folderWithPdfFile
| - - - pdfFile.pdf
| - folderWithExeFile
| - - exeFile.exe
| - - folderWithPngFile
| - - - pngFile.png

使用Files.move(target, destination, StandardCopyOptions.REPLACE_EXISTING)时会抛出DirectoryNotEmptyException;使用Apache Commons IO的FileUtils.moveDirectory(target, destination)时会抛出FileExistsException,以下是可行的合并方案:


方案1:Java原生API递归合并

通过Files.walkFileTree遍历目录结构,逐个处理文件和子目录:

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class DirectoryMerger {
    public static void mergeDirectories(Path source, Path target) throws IOException {
        Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                Path targetDir = target.resolve(source.relativize(dir));
                try {
                    Files.createDirectories(targetDir);
                } catch (FileAlreadyExistsException ignored) {
                    // 目录已存在,跳过继续
                }
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                Path targetFile = target.resolve(source.relativize(file));
                Files.move(file, targetFile, StandardCopyOptions.REPLACE_EXISTING);
                return FileVisitResult.CONTINUE;
            }
        });
        // 合并完成后删除源空目录,不需要可注释该行
        Files.delete(source);
    }

    public static void main(String[] args) throws IOException {
        Path sourceContent = Paths.get("/path/to/source/content");
        Path targetContent = Paths.get("/path/to/target/content");
        mergeDirectories(sourceContent, targetContent);
    }
}

核心逻辑:

  • 遍历源目录的所有节点,先处理目录再处理文件
  • 目标目录不存在则创建,已存在则跳过
  • 移动文件时用REPLACE_EXISTING覆盖同名文件

方案2:Apache Commons IO 复制+删除源目录

利用FileUtils.copyDirectory支持合并的特性,复制后删除源目录模拟移动效果:

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;

public class DirectoryMerger {
    public static void mergeDirectories(File source, File target) throws IOException {
        // 第三个参数设为true:覆盖已存在的文件/目录
        FileUtils.copyDirectory(source, target, true);
        // 删除源目录,不需要可注释该行
        FileUtils.deleteDirectory(source);
    }

    public static void main(String[] args) throws IOException {
        File sourceContent = new File("/path/to/source/content");
        File targetContent = new File("/path/to/target/content");
        mergeDirectories(sourceContent, targetContent);
    }
}

核心逻辑:

  • copyDirectory的第三个参数开启覆盖模式,自动合并目录结构
  • 复制完成后删除源目录,实现类似“移动合并”的效果

方案3:手动递归遍历合并

自己实现递归逻辑处理目录和文件:

import java.io.IOException;
import java.nio.file.*;

public class DirectoryMerger {
    public static void merge(Path source, Path target) throws IOException {
        if (Files.isDirectory(source)) {
            if (!Files.exists(target)) {
                Files.createDirectories(target);
            }
            // 遍历源目录下的所有条目
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(source)) {
                for (Path entry : stream) {
                    Path targetEntry = target.resolve(entry.getFileName());
                    merge(entry, targetEntry);
                }
            }
            Files.delete(source);
        } else {
            Files.move(source, target, StandardCopyOptions.REPLACE_EXISTING);
        }
    }

    public static void main(String[] args) throws IOException {
        Path source = Paths.get("/path/to/source/content");
        Path target = Paths.get("/path/to/target/content");
        merge(source, target);
    }
}

核心逻辑:

  • 递归判断每个路径是目录还是文件
  • 目录不存在则创建,存在则继续处理子条目
  • 文件直接移动并覆盖同名文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:56:04