Delete all files and subdirectories but keep the current directory empty in Java

Viewed 479

I have a folder "/a/b/" and I would like to delete everything inside of folder b, including files, directories and files and subdirectories inside of these directories, but I want to keep folder b empty without delete it. What I have tried was:

Files.walk(Paths.get("/a/b/"))//
                 .map(Path::toFile)//
                 .sorted(Comparator.comparing(File::isDirectory))//
                 .forEach(File::delete);

this solution worked fine when it deleted everything inside of folder b, but it deleted also folder b which I would like to keep. How should I change here to keep folder b, can anyone give me a tip? Thank you

2 Answers

Filter all but this directory :

Path rootPath = Paths.get("/a/b/");
Files.walk(rootPath)//
     .filter(p -> !p.equals(rootPath))
     .map(Path::toFile)//
     .sorted(Comparator.comparing(File::isDirectory))//
     .forEach(File::delete);

Note that .sorted(Comparator.comparing(File::isDirectory)) may not be enough.
Deleting the directories in first instance matters but their deletion order matters too.

Suppose you have directories : /a/b/, /a/b/c, /a/b/c/d.
You want to delete directory depth-last before depth-first, that is /a/b/c/d before /a/b/c.
But File.walk() walks depth-first. So it will iterate in the order : /a/b/, /a/b/c, /a/b/c/d.
So reverse the natural order of the stream of File :

 .sorted(Comparator.reverseOrder())

You can use FileUtils from apache commons-io:

FileUtils.cleanDirectory(Paths.get("/a/b/").toFile()); 

Docs: org.apache.commons.io.FileUtils.cleanDirectory

UPDATED: Only for knowledge, according to documentation for File.walks:

The returned stream encapsulates one or more {@link DirectoryStream}s.
 * If timely disposal of file system resources is required, the
 * {@code try}-with-resources construct should be used to ensure that the
 * stream's {@link Stream#close close} method is invoked after the stream
 * operations are completed.

So, unless you use like this:

try(Stream<Path> paths = Files.walks(...)) {
  //Operations here with paths
}

The stream will no close, even with forEach.

Related