I am trying to investigate a DirecoryStream.Filter
example for newDirectoryStream
where I can achieve to list all files under a directory(and all its sub directories) that are older than 60 days, as an example.
DirectoryStream<Path> dirS = Files.newDirectoryStream(Paths.get("C:/myRootDirectory"), <DirectoryStream.filter>);
for (Path entry: dirS) {
System.out.println(entry.toString());
}
In the code above, what should be the DirectoryStream.filter
?
It will be a great help as I am in a project where I am trying to delete files older than a certain timestamp and pre-java 1.7 File.listFiles()
just hangs.
Could Files.walkFileTree()
provide an option?
If I get this right, you have 2 situations:
filter
to select files older than 60 daysFileTree
) and gather your informationThe custom filter is easier to implement with conditions of 60 days implemented using Calendar
class:
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {BasicFileAttributes attr = Files.readAttributes(entry,BasicFileAttributes.class);
FileTime creationTime = attr.creationTime();
Calendar cal = Calendar.getInstance();
int days = cal.fieldDifference(new Date(creationTime.toMillis()),Calendar.DAY_OF_YEAR);
return (Math.abs(days) > 60);
}
};
The normal execution would only look for the files in the root directory. To look for subdirectory, your guess of using walkFileTree()
is right.
However, this requires an implementation of the FileVisitor
interface, a simple implementation of which luckily is bundled with 7 - SimpleFileVisitor
.
To traverse through the subdirectories, you can choose to override a directory specific method - I have used preVisitDirectory
of SimpleFileVisitor
here:
Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path file,
BasicFileAttributes attrs) {
Since preVisitDirectory
will be custom made to return FileVisitResult.CONTINUE;
in case you don't have any additional restrictions, we would leverage preVisitDirectory
method to iterate through our directory 1 at a time while applying the filter.
Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path file,
BasicFileAttributes attrs) {
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
BasicFileAttributes attr = Files.readAttributes(entry,
BasicFileAttributes.class);
FileTime creationTime = attr.creationTime();
Calendar cal = Calendar.getInstance();
int days = cal.fieldDifference(
new Date(creationTime.toMillis()),
Calendar.DAY_OF_YEAR);
return (Math.abs(days) > 60);
}
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
file, filter)) {
for (Path path : stream) {
System.out.println(path.toString());
}
} catch (IOException ex) {
ex.printStackTrace();
}
return FileVisitResult.CONTINUE;
}
});
This would give you the files from the entire directory and subdirectory structures for the required filter criteria, complete main method below:
public static void main(String[] args) throws IOException {
Path dirs = Paths.get("C:/");
Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path file,
BasicFileAttributes attrs) {
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
BasicFileAttributes attr = Files.readAttributes(entry,
BasicFileAttributes.class);
FileTime creationTime = attr.creationTime();
Calendar cal = Calendar.getInstance();
int days = cal.fieldDifference(
new Date(creationTime.toMillis()),
Calendar.DAY_OF_YEAR);
return (Math.abs(days) > 60);
}
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
file, filter)) {
for (Path path : stream) {
System.out.println(path.toString());
}
} catch (IOException ex) {
ex.printStackTrace();
}
return FileVisitResult.CONTINUE;
}
});
}