|
|
|
|
@ -25,19 +25,21 @@ import javax.annotation.Resource;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.math.BigInteger;
|
|
|
|
|
import java.nio.file.FileVisitResult;
|
|
|
|
|
import java.nio.file.Files;
|
|
|
|
|
import java.nio.file.Path;
|
|
|
|
|
import java.nio.file.SimpleFileVisitor;
|
|
|
|
|
import java.nio.file.attribute.BasicFileAttributes;
|
|
|
|
|
import java.time.*;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
import java.time.temporal.ChronoUnit;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.ArrayBlockingQueue;
|
|
|
|
|
import java.util.concurrent.ThreadPoolExecutor;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
import static java.nio.file.FileVisitResult.CONTINUE;
|
|
|
|
|
|
|
|
|
|
@Component
|
|
|
|
|
@EnableScheduling
|
|
|
|
|
@ -170,7 +172,133 @@ public class CronTab {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private static List<File> getSortedFoldersByCreateTime(File parentDir) {
|
|
|
|
|
File[] folders = parentDir.listFiles(File::isDirectory);
|
|
|
|
|
if (folders == null || folders.length == 0) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Arrays.stream(folders)
|
|
|
|
|
.filter(f -> {
|
|
|
|
|
try {
|
|
|
|
|
Path path = f.toPath();
|
|
|
|
|
BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
|
|
|
|
|
return attr != null && attr.creationTime() != null;
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.sorted(Comparator.comparingLong(f -> {
|
|
|
|
|
try {
|
|
|
|
|
return Files.readAttributes(f.toPath(), BasicFileAttributes.class).creationTime().toMillis();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
return Long.MAX_VALUE;
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 删除旧文件夹,直到磁盘剩余空间大于 350GB
|
|
|
|
|
*
|
|
|
|
|
* @param dirPath 要清理的目录路径
|
|
|
|
|
*/
|
|
|
|
|
public static void deleteUntilFreeSpace(String dirPath) {
|
|
|
|
|
File rootDir = new File(dirPath);
|
|
|
|
|
if (!rootDir.exists() || !rootDir.isDirectory()) {
|
|
|
|
|
log.warn("目标路径不存在或不是目录: {}", dirPath);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
long freeSpaceGB = rootDir.getFreeSpace() / (1024L * 1024L * 1024L);
|
|
|
|
|
if (freeSpaceGB > 350) {
|
|
|
|
|
log.info("磁盘空间已满足要求: {} GB", freeSpaceGB);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取所有可删除的文件和空文件夹,并按创建时间排序
|
|
|
|
|
List<Path> deletableItems = findDeletableItemsSortedByCreateTime(rootDir);
|
|
|
|
|
if (deletableItems.isEmpty()) {
|
|
|
|
|
log.warn("没有更多可删除的文件或文件夹");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除最早的项
|
|
|
|
|
Path oldestItem = deletableItems.get(0);
|
|
|
|
|
try {
|
|
|
|
|
Files.walk(oldestItem)
|
|
|
|
|
.sorted(Comparator.reverseOrder())
|
|
|
|
|
.forEach(path -> {
|
|
|
|
|
try {
|
|
|
|
|
Files.delete(path);
|
|
|
|
|
log.info("已删除: {}", path);
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
log.error("删除失败: {}", path, e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("删除路径时出错: {}", oldestItem, e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class PathWithCreateTime {
|
|
|
|
|
Path path;
|
|
|
|
|
long createTime;
|
|
|
|
|
|
|
|
|
|
PathWithCreateTime(Path path, long createTime) {
|
|
|
|
|
this.path = path;
|
|
|
|
|
this.createTime = createTime;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 查找所有可删除的文件和空文件夹,并按创建时间排序
|
|
|
|
|
*/
|
|
|
|
|
private static List<Path> findDeletableItemsSortedByCreateTime(File rootDir) {
|
|
|
|
|
List<PathWithCreateTime> candidates = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Files.walkFileTree(rootDir.toPath(), new SimpleFileVisitor<>() {
|
|
|
|
|
@Override
|
|
|
|
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
|
|
|
|
if (attrs.isRegularFile()) {
|
|
|
|
|
candidates.add(new PathWithCreateTime(file, attrs.creationTime().toMillis()));
|
|
|
|
|
}
|
|
|
|
|
return CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
|
|
|
|
|
if (exc != null) {
|
|
|
|
|
return CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
// 只收集空文件夹
|
|
|
|
|
if (Files.list(dir).findAny().isEmpty()) {
|
|
|
|
|
BasicFileAttributes attrs = Files.readAttributes(dir, BasicFileAttributes.class);
|
|
|
|
|
candidates.add(new PathWithCreateTime(dir, attrs.creationTime().toMillis()));
|
|
|
|
|
}
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
log.warn("读取文件夹失败: {}", dir, e);
|
|
|
|
|
}
|
|
|
|
|
return CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
log.error("遍历文件系统时出错", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return candidates.stream()
|
|
|
|
|
.sorted(Comparator.comparingLong(p -> p.createTime))
|
|
|
|
|
.map(p -> p.path)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
deleteUntilFreeSpace("D:\\data");
|
|
|
|
|
}
|
|
|
|
|
public static void deleteOldFoldersByName(File parentDir, int days) {
|
|
|
|
|
if (!parentDir.exists() || !parentDir.isDirectory()) {
|
|
|
|
|
System.out.println("指定的路径不是一个有效的目录: " + parentDir.getName());
|
|
|
|
|
|