views:

2562

answers:

6

Is there a way to delete entire directories recursively in Java? In the normal case it is possible to delete an empty directory. However when it comes to deleting entire directories with contents, it is not that simple anymore. How do you delete entire directories with contents in Java?

+11  A: 

How about a recursive method?

void delete(File f) throws IOException {
  if (f.isDirectory()) {
    for (File c : f.listFiles())
      delete(c);
  }
  if (!f.delete())
    throw new FileNotFoundException("Failed to delete file: " + f);
}
erickson
I agree, what you write as an answer is a good solution. However I'd like the File.delete() method handle this case automatically.
lewap
File.delete() does not have that functionality.
Ben S
And *I'd* like a million dollars... Aw crap, where is it?
Software Monkey
@Erickson: Isn't FileNotFoundException a poor exception for a delete failure? If the file is truly no longer there, it must have already been deleted, which means that, semantically, the delete did not fail - it had nothing to do. And if it failed for some other reason, it was not because the file was not found.
Software Monkey
@Software Monkey: I just picked FileNotFoundException because that's what is used for pretty much every file-oriented problem in java.io... permissions, etc. Not great, but the IOException hierarchy is seriously lacking. I hope the NIO2 library does a lot better here.
erickson
Have I missed the base case in this method? :)
JoshJordan
I'm not sure Josh. The base case is when !f.isDirectory(). Is that what you mean?
erickson
A: 

Maybe a solution for this problem might be to reimplement the delete method of the File class using the code from erickson's answer:

public class MyFile extends File {

  ... <- copy constructor

  public boolean delete() {
    if (f.isDirectory()) {
      for (File c : f.listFiles()) {
        return new MyFile(c).delete();
      }
    } else {
        return f.delete();
    }
  }
}
lewap
I think it's implemented as it is to mimic the behavior of most command shell utilities like "rm", "rmdir", and "del". Of the two alternatives, the current implementation definitely minimizes the overall surprise (and anger) potential. It isn't going to change.
erickson
Generally, the only Java JRE packages I see extended are from Swing. Usually, extending other classes such as java.io.File is a bad idea, as it has the possibility to cause things to act in unexpected ways.
Eddie
@Eddie's right. You're also wasting cycles creating MyFile classes that aren't needed if you made the method static.*Also, I don't think this actually deletes the directory, just the files within. you'll end up with a tree of directories with no files in them.I'd go with @Steve K's solution above this one - you shouldn't have to maintain/debug code like this if it's readily available from a common framework library like apache commons.
Kevin Williams
+15  A: 

You should check out Apache's commons-io. It has a FileUtils class that will do what you want.

FileUtils.deleteDirectory(new File("directory"));
Steve K
This function probably wraps the code that erickson provided in his answer.
lewap
It's a little more thorough. It handles things like symbolic links correctly on Linux/Unix. http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/FileUtils.java?view=markup
Steve K
I'd strongly recommend this, rather than having to re-implement that recursive method in nearly every project I touch :-( Not that it's bad/wrong, but the Commons stuff now delivers so much value
Brian Agnew
I wonder why FileUtils.deleteDirectory throws IOException where File.delete() doesn't.
oksayt
A: 
glue
YOur error messages are really poor, if i come back and run this in a years time what does failure mean ? Why not actually include a real description in the two messages...
mP
I did not intend for this to be exhaustive. Like I posted, this is a bare bones example that may be manipulated to how one sees fit. If I were to actually write this for myself, I would definitely have more error checking and more descriptive messages. However, I agree that it may have been needed to point out the necessity of better descriptions, so, thanks!
glue
A: 

Guava has Files.deleteRecursively

Andrew McKinlay
+1  A: 

Just saw my solution is more or less the same as erickson's, just packaged as a static method. Drop this somewhere, it's much lighter weight than installing all of Apache Commons for something that (as you can see) is quite simple.

public class FileUtils {
    /**
     * By default File#delete fails for non-empty directories, it works like "rm". 
     * We need something a little more brutual - this does the equivalent of "rm -r"
     * @param path Root File Path
     * @return true iff the file and all sub files/directories have been removed
     * @throws FileNotFoundException
     */
    public static boolean deleteRecursive(File path) throws FileNotFoundException{
        if (!path.exists()) throw new FileNotFoundException(path.getAbsolutePath());
        boolean ret = true;
        if (path.isDirectory()){
            for (File f : path.listFiles()){
                ret = ret && FileUtils.deleteRecursive(f);
            }
        }
        return ret && path.delete();
    }
}
Paulitex