Java中递归删除目录
有没有办法在Java中递归删除整个目录?
在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,事情就不再那么简单了。
如何在 Java 中删除包含内容的整个目录?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(26)
您应该查看 Apache 的 commons-io。 它有一个 FileUtils 类将执行您想要的操作。
You should check out Apache's commons-io. It has a FileUtils class that will do what you want.
有了 Java 7,我们终于可以通过可靠的符号链接检测来做到这一点。(我不认为 Apache 的 commons-io 有目前可靠符号链接检测,因为它不处理 Windows 上使用
mklink
创建的链接。)为了历史记录,这里有一个 Java 7 之前的答案,其中跟随符号链接。
With Java 7, we can finally do this with reliable symlink detection. (I don't consider Apache's commons-io to have reliable symlink detection at this time, as it doesn't handle links on Windows created with
mklink
.)For the sake of history, here's a pre-Java 7 answer, which follows symlinks.
在 Java 7+ 中,您可以使用
Files
< /a> 类。 代码非常简单:In Java 7+ you can use
Files
class. Code is very simple:单行解决方案(Java8)递归删除所有文件和目录,包括起始目录:
我们使用比较器进行相反的顺序,否则 File::delete 将无法删除可能的非空目录。 因此,如果您想保留目录并仅删除文件,只需删除排序()中的比较器或完全删除排序并添加文件过滤器:
One-liner solution (Java8) to delete all files and directories recursively including starting directory:
We use a comparator for reversed order, otherwise File::delete won't be able to delete possibly non-empty directory. So, if you want to keep directories and only delete files just remove the comparator in sorted() or remove sorting completely and add files filter:
Java 7 添加了对带有符号链接处理的行走目录的支持:
我使用它作为特定于平台的方法的后备(在此未经测试的代码中):(
SystemUtils 来自 Apache Commons Lang。进程是私有的,但其行为应该是显而易见的。)
Java 7 added support for walking directories with symlink handling:
I use this as a fallback from platform-specific methods (in this untested code):
(SystemUtils is from Apache Commons Lang. Processes is private but its behavior should be obvious.)
刚刚看到我的解决方案与埃里克森的解决方案或多或少相同,只是打包为静态方法。 把它放在某个地方,它比安装所有 Apache Commons 的重量要轻得多,因为(如您所见)非常简单。
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.
使用堆栈且不使用递归方法的解决方案:
A solution with a stack and without recursive methods:
如果你有Spring,你可以使用 FileSystemUtils.deleteRecursively:
If you have Spring, you can use FileSystemUtils.deleteRecursively:
Guava 有
Files.deleteRecursively(File)
支持直至番石榴 9。来自 番石榴 10:
因此,番石榴 11。
Guava had
Files.deleteRecursively(File)
supported until Guava 9.From Guava 10:
Therefore, there is no such method in Guava 11.
或者,如果您想处理 IOException:
Or if you want to handle the
IOException
:符号链接和上面的代码有两种失败的方法......并且不知道解决方案。
方法#1
运行此命令来创建测试:
在这里您可以看到测试文件和测试目录:
然后运行 commons-io deleteDirectory()。 它崩溃说找不到该文件。 不确定其他示例在这里做什么。 Linux rm 命令只会删除链接,目录上的 rm -r 也会删除。
方法#2
运行此命令来创建测试:
在这里您可以看到测试文件和测试目录:
然后运行 commons-io deleteDirectory() 或人们发布的示例代码。 它不仅删除目录,还删除位于被删除目录之外的测试文件。 (它隐式取消引用目录,并删除内容)。 rm -r 只会删除链接。 您需要使用类似的方法删除取消引用的文件:“find -L dirtydelete -type f -exec rm {} \;”。
Two ways to fail with symlinks and the above code... and don't know the solution.
Way #1
Run this to create a test:
Here you see your test file and test directory:
Then run your commons-io deleteDirectory(). It crashes saying the file is not found. Not sure what the other examples do here. The Linux rm command would simply delete the link, and rm -r on the directory would also.
Way #2
Run this to create a test:
Here you see your test file and test directory:
Then run your commons-io deleteDirectory() or the example code people posted. It deletes not only the directory, but your testfile which is outside the directory being deleted. (It dereferences the directory implicitly, and deletes the contents). rm -r would delete the link only. You need to use something like this delete the dereferenced files: "find -L dirtodelete -type f -exec rm {} \;".
您可以使用:
org.apache.commons.io.FileUtils.deleteQuietly(destFile);
删除文件,从不引发异常。 如果 file 是一个目录,则删除它和所有子目录。
File.delete() 与该方法的区别是:
要删除的目录不必为空。
无法删除文件或目录时不会抛出异常。
You could use:
org.apache.commons.io.FileUtils.deleteQuietly(destFile);
Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories.
The difference between File.delete() and this method are:
A directory to be deleted does not have to be empty.
No exceptions are thrown when a file or directory cannot be deleted.
处理异常的最佳解决方案与从方法引发的异常应始终描述该方法尝试(和失败)执行的操作的方法一致:
An optimal solution that handles exception consistently with the approach that an exception thrown from a method should always describe what that method was trying (and failed) to do:
在遗留项目中,我需要创建本机 Java 代码。 我创建的代码与 Paulitex 代码类似。 看到:
和单元测试:
In legacy projects, I need to create native Java code. I create this code similar to Paulitex code. See that:
And the unit test:
下面的代码递归删除给定文件夹中的所有内容。
Below code recursively delete all contents in a given folder.
这是一个接受命令行参数的简单 main 方法,您可能需要附加自己的错误检查或将其塑造为您认为合适的方式。
我希望这有帮助!
Here is a bare bones main method that accepts a command line argument, you may need to append your own error checking or mold it to how you see fit.
I hope that helps!
Guava 提供了一句:
MoreFiles。递归地删除()
。与许多共享的示例不同,它考虑符号链接,并且不会(默认情况下)删除提供的路径之外的文件。
Guava provides a one-liner:
MoreFiles.deleteRecursively()
.Unlike many of the examples shared, it accounts for symbolic links and will not (by default) delete files outside the provided path.
也许这个问题的解决方案可能是使用埃里克森答案中的代码重新实现 File 类的删除方法:
Maybe a solution for this problem might be to reimplement the delete method of the File class using the code from erickson's answer:
没有 Commons IO 且 < Java SE 7
Without Commons IO and < Java SE 7
// Java 8 与 lambda & 流,如果参数是目录
// 如果参数是文件或目录
// Java 8 with lambda & stream, if param is directory
// if param is file or directory
Guava 21.0 及更高
版本 自 Guava 21.0 起,
MoreFiles
类的void deleteRecursively(Path path, RecursiveDeleteOption... options) throws IOException
静态方法可用。请参阅 Javadoc 文档:
Guava 21.0 and later
There is the
void deleteRecursively(Path path, RecursiveDeleteOption... options) throws IOException
static method of theMoreFiles
class available since Guava 21.0.Please, see the Javadoc documentation:
rm -rf
比FileUtils.deleteDirectory
性能高得多。经过广泛的基准测试,我们发现使用 rm -rf 比使用 FileUtils.deleteDirectory 快数倍。
当然,如果您有一个小或简单的目录,那没关系,但在我们的例子中,我们有多个千兆字节和深度嵌套的子目录,使用
FileUtils.deleteDirectory
需要花费 10 分钟以上,并且仅使用rm -rf
需要 1 分钟。这是我们的粗略 Java 实现:
如果您正在处理大型或复杂的目录,值得尝试。
rm -rf
was much more performant thanFileUtils.deleteDirectory
.After extensive benchmarking, we found that using
rm -rf
was multiple times faster than usingFileUtils.deleteDirectory
.Of course, if you have a small or simple directory, it won't matter but in our case we had multiple gigabytes and deeply nested sub directories where it would take over 10 minutes with
FileUtils.deleteDirectory
and only 1 minute withrm -rf
.Here's our rough Java implementation to do that:
Worth trying if you're dealing with large or complex directories.
虽然可以使用 file.delete() 轻松删除文件,但目录必须为空才能删除。 使用递归可以轻松地做到这一点。 例如:
While files can easily be deleted using file.delete(), directories are required to be empty to be deleted. Use recursion to do this easily. For example:
我编写了这个例程,它具有 3 个安全标准,以便更安全地使用。
i coded this routine that has 3 safety criteria for safer use.