PathUtil增加loopFiles重载,可选是否追踪软链

This commit is contained in:
Looly 2023-10-27 22:43:17 +08:00
parent eeed094f92
commit 5af0894911

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.core.io.file;
import org.dromara.hutool.core.collection.set.SetUtil;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.util.CharsetUtil;
@ -23,6 +24,7 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
/**
* NIO中Path对象操作封装
@ -71,11 +73,26 @@ public class PathUtil {
* @since 5.4.1
*/
public static List<File> loopFiles(final Path path, final int maxDepth, final FileFilter fileFilter) {
return loopFiles(path, maxDepth, false, fileFilter);
}
/**
* 递归遍历目录以及子目录中的所有文件<br>
* 如果提供path为文件直接返回过滤结果
*
* @param path 当前遍历文件或目录
* @param maxDepth 遍历最大深度-1表示遍历到没有目录为止
* @param isFollowLinks 是否跟踪软链快捷方式
* @param fileFilter 文件过滤规则对象选择要保留的文件只对文件有效不过滤目录null表示接收全部文件
* @return 文件列表
* @since 5.4.1
*/
public static List<File> loopFiles(final Path path, final int maxDepth, final boolean isFollowLinks, final FileFilter fileFilter) {
final List<File> fileList = new ArrayList<>();
if (null == path || !Files.exists(path)) {
if (!exists(path, isFollowLinks)) {
return fileList;
} else if (!isDirectory(path)) {
} else if (!isDirectory(path, isFollowLinks)) {
final File file = path.toFile();
if (null == fileFilter || fileFilter.accept(file)) {
fileList.add(file);
@ -83,7 +100,7 @@ public class PathUtil {
return fileList;
}
walkFiles(path, maxDepth, new SimpleFileVisitor<Path>() {
walkFiles(path, maxDepth, isFollowLinks, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(final Path path, final BasicFileAttributes attrs) {
@ -119,14 +136,28 @@ public class PathUtil {
* @see Files#walkFileTree(Path, java.util.Set, int, FileVisitor)
* @since 4.6.3
*/
public static void walkFiles(final Path start, int maxDepth, final FileVisitor<? super Path> visitor) {
public static void walkFiles(final Path start, final int maxDepth, final FileVisitor<? super Path> visitor) {
walkFiles(start, maxDepth, false, visitor);
}
/**
* 遍历指定path下的文件并做处理
*
* @param start 起始路径必须为目录
* @param maxDepth 最大遍历深度-1表示不限制深度
* @param visitor {@link FileVisitor} 接口用于自定义在访问文件时访问目录前后等节点做的操作
* @param isFollowLinks 是否追踪到软链对应的真实地址
* @see Files#walkFileTree(Path, java.util.Set, int, FileVisitor)
* @since 5.8.23
*/
public static void walkFiles(final Path start, int maxDepth, final boolean isFollowLinks, final FileVisitor<? super Path> visitor) {
if (maxDepth < 0) {
// < 0 表示遍历到最底层
maxDepth = Integer.MAX_VALUE;
}
try {
Files.walkFileTree(start, EnumSet.noneOf(FileVisitOption.class), maxDepth, visitor);
Files.walkFileTree(start, getFileVisitOption(isFollowLinks), maxDepth, visitor);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
@ -238,8 +269,7 @@ public class PathUtil {
if (null == path) {
return false;
}
final LinkOption[] options = isFollowLinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
return Files.isDirectory(path, options);
return Files.isDirectory(path, getLinkOptions(isFollowLinks));
}
/**
@ -323,9 +353,8 @@ public class PathUtil {
return null;
}
final LinkOption[] options = isFollowLinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
try {
return Files.readAttributes(path, BasicFileAttributes.class, options);
return Files.readAttributes(path, BasicFileAttributes.class, getLinkOptions(isFollowLinks));
} catch (final IOException e) {
throw new IORuntimeException(e);
}
@ -497,8 +526,7 @@ public class PathUtil {
if (null == path) {
return false;
}
final LinkOption[] options = isFollowLinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
return Files.isRegularFile(path, options);
return Files.isRegularFile(path, getLinkOptions(isFollowLinks));
}
/**
@ -535,8 +563,7 @@ public class PathUtil {
if (null == path) {
return false;
}
final LinkOption[] options = isFollowLinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
return Files.exists(path, options);
return Files.exists(path, getLinkOptions(isFollowLinks));
}
/**
@ -663,11 +690,35 @@ public class PathUtil {
} else {
return Files.createTempFile(mkdir(dir), prefix, suffix);
}
} catch (final IOException ioex) { // fixes java.io.WinNTFileSystem.createFileExclusively access denied
} catch (final IOException ioex) {
// fixes java.io.WinNTFileSystem.createFileExclusively access denied
if (++exceptionsCount >= 50) {
throw new IORuntimeException(ioex);
}
}
}
}
/**
* 构建是否追踪软链的选项
*
* @param isFollowLinks 是否追踪软链
* @return 选项
* @since 5.8.23
*/
public static LinkOption[] getLinkOptions(final boolean isFollowLinks) {
return isFollowLinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
}
/**
* 构建是否追踪软链的选项
*
* @param isFollowLinks 是否追踪软链
* @return 选项
* @since 5.8.23
*/
public static Set<FileVisitOption> getFileVisitOption(final boolean isFollowLinks) {
return isFollowLinks ? EnumSet.of(FileVisitOption.FOLLOW_LINKS) :
EnumSet.noneOf(FileVisitOption.class);
}
}