java - Java将带有文件和结构的子目录移动到父目录
问题描述
试图将文件从子目录连同结构一起移动到父目录。我无法使用Files.move()
. 为了说明这个问题,请参见下面的目录结构。
$ tree
.
└── b
├── c
│ ├── cfile.gtxgt
│ └── d
│ ├── dfile.txt
│ └── e
└── x
└── y
└── z
├── 2.txt
└── p
├── file1.txt
└── q
├── file
├── file2.txt
└── r
└── 123.txt
我想通过 Java 模拟下面的移动命令。
$ mv b/x/y/z/* b/c
b/x/y/z/2.txt -> b/c/2.txt
b/x/y/z/p -> b/c/p
并且输出应该类似于
$ tree
.
└── b
├── c
│ ├── 2.txt
│ ├── cfile.gtxgt
│ ├── d
│ │ ├── dfile.txt
│ │ └── e
│ └── p
│ ├── file1.txt
│ └── q
│ ├── file
│ ├── file2.txt
│ └── r
│ └── 123.txt
└── x
└── y
└── z
在此移动中,目录下的所有文件和目录z
都已移动到c
.
我试图这样做:
public static void main(String[] args) throws IOException{
String aPath = "/tmp/test/a/";
String relativePathTomove = "b/x/y/z/";
String relativePathToMoveTo = "b/c";
Files.move(Paths.get(aPath, relativePathTomove), Paths.get(aPath, relativePathToMoveTo), StandardCopyOption.REPLACE_EXISTING);
}
但是,这会导致抛出此异常java.nio.file.DirectoryNotEmptyException: /tmp/test/a/b/c
,如果REPLACE_EXISTING
取出该选项,则代码会抛出java.nio.file.FileAlreadyExistsException: /tmp/test/a/b/c
.
这个问题有一个使用递归函数来解决这个问题的答案。但就我而言,这将涉及进一步的复杂性,因为我什至需要在新位置重新创建子目录结构。
我没有尝试使用commons-io
实用程序方法的选项,org.apache.commons.io.FileUtils#moveDirectoryToDirectory
因为此代码似乎首先复制文件,然后从原始位置删除它们。就我而言,文件很大,因此这不是首选。
如何在不借助复制的情况下实现 java 中的移动功能。单个文件移动是我唯一的选择吗?
TLDR:我如何mv
在 java 中模拟将带有文件和结构的子目录移动到父目录的功能。
解决方案
我最终这样做了:
像这样创建一个FileVisitor
实现:
package com.test.files;
import org.apache.log4j.Logger;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Objects;
import static java.nio.file.FileVisitResult.TERMINATE;
public class MoveFileVisitor implements FileVisitor<Path> {
private static final Logger LOGGER = Logger.getLogger(MoveFileVisitor.class);
private final Path target;
private final Path source;
public MoveFileVisitor(@NotNull Path source, @NotNull Path target) {
this.target = Objects.requireNonNull(target);
this.source = Objects.requireNonNull(source);
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
Path relativePath = source.relativize(dir);
Path finalPath = target.resolve(relativePath);
Files.createDirectories(finalPath);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path relativePath = source.relativize(file);
Path finalLocation = target.resolve(relativePath);
Files.move(file, finalLocation);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
LOGGER.error("Failed to visit file during move" + file.toAbsolutePath(), exc);
return TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
}
然后像这样和这个访客一起走这条路:
String source = "/temp/test/a/b/x/y/z";
String target = "/temp/test/a/b/c";
MoveFileVisitor visitor = new MoveFileVisitor(Paths.get(source), Paths.get(target));
Files.walkFileTree(Paths.get(source), visitor);
推荐阅读
- .net-core - 在 SQL Server 上添加种子数据
- typescript - 将函数参数约束为从不消除映射类型不满足约束的无效代码路径
- r - 评估者与 kappa 之间的协议,使用 tidyverse 和循环函数来旋转数据(数据集)
- c# - 关于eShopOnContainers api网关路由前缀的问题
- java - 如何将依赖项包含到 JAR 文件中(Maven)
- pivot - 在 Snowflake 中使用 Count Distinct 和 Pivot
- r - 如何在 R 包中包含和显示图像?
- postgresql - 仅选择唯一 ID 的最近日期
- pdo - 占位符在准备好的语句中不起作用
- javascript - 如何更改简单表单提交按钮以路由到另一个简单表单