Java NIO2 (Path, Files, FileVisitor)
I'm using 2 classes that implements FileVisitor
interface.
The first one detects all folders/subfolders that has been modified before X period of time.
The second one deletes all folders stored by the first class
Files.walkFileTree(Path, FileVisitor<Class>)
is used to walk through directories.
All classes inside one (you can extract FileVisitorFolders
and FileVisitorDeleteFolders
to class file
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.Period;
import java.util.ArrayList;
public class Main {
private static class FileVisitorFolders implements FileVisitor<Path> {
private Instant beforePeriodOfTime;
private ArrayList<Path> directories = new ArrayList<>(10);
public FileVisitorFolders(Period time) {
beforePeriodOfTime = Instant.now().minus(time);
}
public ArrayList<Path> getDirectories() {
return directories;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
var lastModifiedTime = Files.getLastModifiedTime(dir, LinkOption.NOFOLLOW_LINKS);
if (lastModifiedTime.toInstant().isBefore(beforePeriodOfTime)) {
directories.add(dir);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
}
private static class FileVisitorDeleteFolders implements FileVisitor<Path> {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
}
public static void main(String[] args) {
var fileVisitorFolders = new FileVisitorFolders(Period.ofDays(1));
var fileVisitorDeleteFolder = new FileVisitorDeleteFolders();
try {
Files.walkFileTree(Paths.get("testFolder"), fileVisitorFolders);
for (Path dir : fileVisitorFolders.getDirectories()) {
System.out.printf("Deleting: %s\n", dir.toAbsolutePath().toString());
Files.walkFileTree(dir, fileVisitorDeleteFolder);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
How it works?
Here we have the next directories: (Note: Today is 2018-06-18)
tree -D testFolder/
testFolder/
├── [Jun 17 5:00] a
├── [Jun 18 18:06] b
├── [Jun 15 5:00] c
│ ├── [Jun 18 18:06] e
│ └── [Jun 18 18:06] hi
└── [Jun 18 17:30] e
5 directories, 1 file
The folders a
has been modified 1 day ago and the folder c
has been modified 3 days ago.
The folder a
is empty and the folder c
have a subfolder e
and a file hi
The main method is:
public static void main(String[] args) {
var fileVisitorFolders = new FileVisitorFolders(Period.ofDays(1));
var fileVisitorDeleteFolder = new FileVisitorDeleteFolders();
try {
Files.walkFileTree(Paths.get("testFolder"), fileVisitorFolders);
for (Path dir : fileVisitorFolders.getDirectories()) {
System.out.printf("Deleting: %s\n", dir.toAbsolutePath().toString());
Files.walkFileTree(dir, fileVisitorDeleteFolder);
}
} catch (IOException e) {
e.printStackTrace();
}
}
- Check recursively all subfolders of
testFolder
and save a Path of every folder than has been modified before this period of time: Period.ofDays(1)
- Delete (recursively) all folders saved previously (Paths)
Output:
Deleting: /root/IdeaProjects/DeleteFolder/testFolder/a
Deleting: /root/IdeaProjects/DeleteFolder/testFolder/c
Process finished with exit code 0
Now we have:
tree -D testFolder/
testFolder/
├── [Jun 18 18:06] b
└── [Jun 18 17:30] e
2 directories, 0 files
Note: Before use it, test it commenting the line: //Files.walkFileTree(dir, fileVisitorDeleteFolder);
To change the date of last modified file/folder (on Linux) you can use the command touch
like:
touch -m -t 201806150700 folderName/fileName
-m
-> last modified time
-t
-> time
If you want less code, use extends SimpleFileVisitor
instead implements FileVisitor
and only implements the necessary methods (omit all empty methods)
If you are using Java before 1.10 replace var
with the instance type.
Important
Be carefull with this code. If the parent folder (in this case: testFolder) has not been modified in the last period of time it will be deleted too.
To avoid this situation you can modify the main method:
public static void main(String[] args) {
var parent = Paths.get("testFolder");
var fileVisitorFolders = new FileVisitorFolders(Period.ofDays(1));
var fileVisitorDeleteFolder = new FileVisitorDeleteFolders();
try {
Files.walkFileTree(parent, fileVisitorFolders);
var foldersToDelete = fileVisitorFolder.getDirectories();
foldersToDelete.remove(parent);
for (Path dir : foldersToDelete) {
System.out.printf("Deleting: %s\n", dir.toAbsolutePath().toString());
Files.walkFileTree(dir, fileVisitorDeleteFolder);
}
} catch (IOException e) {
e.printStackTrace();
}
}