简体   繁体   中英

Java delete file/directory equivalent of linux “rm -rf /tmp/garbagedir*”

Given a bunch of tmp directories and tmp files like this:

/tmp/garbagedir1/
/tmp/garbagedir2/
/tmp/garbagedir3/
/tmp/deleteme.txt
/tmp/deleteme.log

In Linux, we can execute one simple shell command to recursively force delete all of these:

$ rm -rf /tmp/garbagedir* /tmp/deleteme*

All of the above files and directories are deleted, including all the files that may be in the directories. All other files in the /tmp directory are not touched.

There are many ways to do this in Java, but what is the simplest way that does not involve lots of Java style boilerplate code and still be platform independent?

you may use the FileUtils class of Apache Commons IO; with it you can do something like that:

FileUtils.forceDelete(new File("/home/test"));

Links to the documentation: http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html

Hope it helps

Angelo

Note, I haven't tested this code so don't try it first on anything important!

You can use the Java NIO2 SimpleFileVisitor to recursviely walk thru directories and their children. First we create a new FileVisitor that will delete all files that it sees and then delete the empty directories once all its children have been deleted.

  FileVisitor recursiveDeleteVisitor = new SimpleFileVisitor<Path>() {

  @Override
  public FileVisitResult visitFile(Path file,
          BasicFileAttributes attrs) throws IOException {

      System.out.println("Deleting file: " + file);
      Files.delete(file);
      return CONTINUE;
  }

  @Override
  public FileVisitResult postVisitDirectory(Path dir,
          IOException exc) throws IOException {

      System.out.println("Deleting dir: " + dir);
      if (exc == null) {
          Files.delete(dir);
          return CONTINUE;
      } else {
          throw exc;
      }
  }

 };

This might count as boiler plate, but you would only have to write the FileVisitor instance once and then you can re-use it as part of a utility class. I'm not sure why something like this isn't included in the JDK.

Anyway, once you have that, then iterate over the children of /tmp and recursively delete any directories that match:

 File root = new File("/tmp");
 for(File child : root.listFiles()){
      //optionally use Pattern class for regex
      if(child.getName().startsWith("garbagedir")){
          Files.walkFileTree(child.toPath(), recursiveDeleteVisitor);
      }
 }

EDIT


User fge pointed out that Java 7 has a Files.newDirectoryStream() method that will return a DirectoryStream object that can be used to iterate over the children instead of using the old File.listFiles() which returns an array which means all the objects are created in memory before iteration. This could save you from memory problems if you have lots of files. You can even use the globbing pattern as a 2nd String argument.

Path root = Paths.get("/tmp");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(root, "garbagedir*")) {
   for (Path entry: stream) {
       Files.walkFileTree(child.toPath(), recursiveDeleteVisitor);
    }
 }

The new file API has all the tools you need:

Feel free to salvage the recursive deletion example, and note that it can be improved. In particular, this one will stop at the first deletion error, but it is trivial to modify so that it continues in this case instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM