在Java中是否有一种方法可以递归地删除整个目录?

在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,就不再那么简单了。

如何在Java中删除包含内容的整个目录?


当前回答

在遗留项目中,我需要创建本地Java代码。我创建了类似于Paulitex代码的代码。看到:

public class FileHelper {

   public static boolean delete(File fileOrFolder) {
      boolean result = true;
      if(fileOrFolder.isDirectory()) {
         for (File file : fileOrFolder.listFiles()) {
            result = result && delete(file);
         }
      }
      result = result && fileOrFolder.delete();
      return result;
   } 
}

单元测试:

public class FileHelperTest {

    @Before
    public void setup() throws IOException {
       new File("FOLDER_TO_DELETE/SUBFOLDER").mkdirs();
       new File("FOLDER_TO_DELETE/SUBFOLDER_TWO").mkdirs();
       new File("FOLDER_TO_DELETE/SUBFOLDER_TWO/TEST_FILE.txt").createNewFile();
    }

    @Test
    public void deleteFolderWithFiles() {
       File folderToDelete = new File("FOLDER_TO_DELETE");
       Assert.assertTrue(FileHelper.delete(folderToDelete));
       Assert.assertFalse(new File("FOLDER_TO_DELETE").exists());
    }

}

其他回答

public static void deleteDirectory(File path) 
{
    if (path == null)
        return;
    if (path.exists())
    {
        for(File f : path.listFiles())
        {
            if(f.isDirectory()) 
            {
                deleteDirectory(f);
                f.delete();
            }
            else
            {
                f.delete();
            }
        }
        path.delete();
    }
}

使用符号链接和上面的代码失败的两种方式…也不知道怎么解决。

方法# 1

运行这个来创建一个测试:

echo test > testfile
mkdir dirtodelete
ln -s badlink dirtodelete/badlinktodelete

下面你可以看到你的测试文件和测试目录:

$ ls testfile dirtodelete
testfile

dirtodelete:
linktodelete

然后运行common -io deleteDirectory()。它崩溃,说文件没有找到。不知道其他例子是怎么做的。Linux的rm命令会简单地删除链接,目录上的rm -r也会删除链接。

Exception in thread "main" java.io.FileNotFoundException: File does not exist: /tmp/dirtodelete/linktodelete

方法# 2

运行这个来创建一个测试:

mkdir testdir
echo test > testdir/testfile
mkdir dirtodelete
ln -s ../testdir dirtodelete/dirlinktodelete

下面你可以看到你的测试文件和测试目录:

$ ls dirtodelete testdir
dirtodelete:
dirlinktodelete

testdir:
testfile

然后运行common -io deleteDirectory()或人们发布的示例代码。它不仅会删除目录,还会删除位于被删除目录之外的testfile。(它隐式地取消对目录的引用,并删除内容)。Rm -r只会删除链接。你需要使用类似这样的方法删除被解引用的文件:"find -L dirtodelete -type f -exec rm {} \;"

$ ls dirtodelete testdir
ls: cannot access dirtodelete: No such file or directory
testdir:

在Java 7中,我们终于可以通过可靠的符号链接检测来做到这一点。(我不认为Apache的commons-io现在有可靠的符号链接检测,因为它不处理Windows上用mklink创建的链接。)

出于历史原因,这里有一个java 7之前的答案,它遵循符号链接。

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);
}

没有Commons IO和< Java SE 7

public static void deleteRecursive(File path){
            path.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    if (pathname.isDirectory()) {
                        pathname.listFiles(this);
                        pathname.delete();
                    } else {
                        pathname.delete();
                    }
                    return false;
                }
            });
            path.delete();
        }

处理异常的最佳解决方案是,方法抛出的异常应该总是描述该方法试图(和失败)做什么:

private void deleteRecursive(File f) throws Exception {
    try {
        if (f.isDirectory()) {
            for (File c : f.listFiles()) {
                deleteRecursive(c);
            }
        }
        if (!f.delete()) {
            throw new Exception("Delete command returned false for file: " + f);
        }
    } 
    catch (Exception e) {
        throw new Exception("Failed to delete the folder: " + f, e);
    }
}