paw*_*que 369 java filesystems file-io delete-directory
有没有办法在Java中递归删除整个目录?
在正常情况下,可以删除空目录.但是,当要删除包含内容的整个目录时,它就不再那么简单了.
如何用Java中的内容删除整个目录?
Ste*_*e K 454
你应该查看Apache的commons-io.它有一个FileUtils类,可以做你想要的.
FileUtils.deleteDirectory(new File("directory"));
Run Code Online (Sandbox Code Playgroud)
eri*_*son 189
使用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);
}
Run Code Online (Sandbox Code Playgroud)
Tom*_*ski 144
在Java 7+中,您可以使用Files类.代码很简单:
Path directory = Paths.get("/tmp");
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
Run Code Online (Sandbox Code Playgroud)
Tre*_*son 67
Java 7添加了对带有符号链接处理的步行目录的支持:
import java.nio.file.*;
public static void removeRecursive(Path path) throws IOException
{
Files.walkFileTree(path, new SimpleFileVisitor<Path>()
{
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException
{
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
{
// try to delete the file anyway, even if its attributes
// could not be read, since delete-only access is
// theoretically possible
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException
{
if (exc == null)
{
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
else
{
// directory iteration failed; propagate exception
throw exc;
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
我使用它作为特定于平台的方法的后备(在这个未经测试的代码中):
public static void removeDirectory(Path directory) throws IOException
{
// does nothing if non-existent
if (Files.exists(directory))
{
try
{
// prefer OS-dependent directory removal tool
if (SystemUtils.IS_OS_WINDOWS)
Processes.execute("%ComSpec%", "/C", "RD /S /Q \"" + directory + '"');
else if (SystemUtils.IS_OS_UNIX)
Processes.execute("/bin/rm", "-rf", directory.toString());
}
catch (ProcessExecutionException | InterruptedException e)
{
// fallback to internal implementation on error
}
if (Files.exists(directory))
removeRecursive(directory);
}
}
Run Code Online (Sandbox Code Playgroud)
(SystemUtils来自Apache Commons Lang.进程是私有的,但其行为应该是显而易见的.)
RoK*_*RoK 62
单行解决方案(Java8)以递归方式删除所有文件和目录,包括起始目录:
Files.walk(Paths.get("c:/dir_to_delete/"))
.map(Path::toFile)
.sorted((o1, o2) -> -o1.compareTo(o2))
.forEach(File::delete);
Run Code Online (Sandbox Code Playgroud)
我们使用比较器反转顺序,否则File :: delete将无法删除可能的非空目录.因此,如果您想保留目录并且只删除文件,只需删除sorted()中的比较器或完全删除排序并添加文件过滤器:
Files.walk(Paths.get("c:/dir_to_delete/"))
.filter(Files::isRegularFile)
.map(Path::toFile)
.forEach(File::delete);
Run Code Online (Sandbox Code Playgroud)
Pau*_*tex 32
刚刚看到我的解决方案与erickson的解决方案大致相同,只是打包为静态方法.把它放在某个地方,它比安装所有Apache Commons的重量要轻得多(如你所见)非常简单.
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 && deleteRecursive(f);
}
}
return ret && path.delete();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 19
具有堆栈且没有递归方法的解决方案:
File dir = new File("/path/to/dir");
File[] currList;
Stack<File> stack = new Stack<File>();
stack.push(dir);
while (! stack.isEmpty()) {
if (stack.lastElement().isDirectory()) {
currList = stack.lastElement().listFiles();
if (currList.length > 0) {
for (File curr: currList) {
stack.push(curr);
}
} else {
stack.pop().delete();
}
} else {
stack.pop().delete();
}
}
Run Code Online (Sandbox Code Playgroud)
And*_*lay 15
番石榴一直Files.deleteRecursively(File)支持到番石榴9.
来自番石榴10:
已过时.该方法存在差的符号链检测和竞争条件.仅通过外壳到诸如
rm -rf或的操作系统命令,可以适当地支持此功能del /s.计划在Guava版本11.0中从Guava中删除此方法.
因此,番石榴11中没有这样的方法.
Ben*_*son 14
如果你有Spring,你可以使用FileSystemUtils.deleteRecursively:
import org.springframework.util.FileSystemUtils;
boolean success = FileSystemUtils.deleteRecursively(new File("directory"));
Run Code Online (Sandbox Code Playgroud)
use*_*782 12
for(Path p : Files.walk(directoryToDelete).
sorted((a, b) -> b.compareTo(a)). // reverse; files before dirs
toArray(Path[]::new))
{
Files.delete(p);
}
Run Code Online (Sandbox Code Playgroud)
或者如果你想处理IOException:
Files.walk(directoryToDelete).
sorted((a, b) -> b.compareTo(a)). // reverse; files before dirs
forEach(p -> {
try { Files.delete(p); }
catch(IOException e) { /* ... */ }
});
Run Code Online (Sandbox Code Playgroud)
Ada*_*ler 11
public void deleteRecursive(File path){
File[] c = path.listFiles();
System.out.println("Cleaning out folder:" + path.toString());
for (File file : c){
if (file.isDirectory()){
System.out.println("Deleting file:" + file.toString());
deleteRecursive(file);
file.delete();
} else {
file.delete();
}
}
path.delete();
}
Run Code Online (Sandbox Code Playgroud)
小智 8
static public 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();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
符号链接和上面的代码失败的两种方法...不知道解决方案。
运行此命令以创建测试:
echo test > testfile
mkdir dirtodelete
ln -s badlink dirtodelete/badlinktodelete
Run Code Online (Sandbox Code Playgroud)
在这里,您可以看到测试文件和测试目录:
$ ls testfile dirtodelete
testfile
dirtodelete:
linktodeleteRun Code Online (Sandbox Code Playgroud)
然后运行commons-io deleteDirectory()。崩溃提示找不到文件。不知道其他示例在这里做什么。Linux rm命令将只删除链接,目录中的rm -r也将删除。
Exception in thread "main" java.io.FileNotFoundException: File does not exist: /tmp/dirtodelete/linktodeleteRun Code Online (Sandbox Code Playgroud)
运行此命令以创建测试:
mkdir testdir
echo test > testdir/testfile
mkdir dirtodelete
ln -s ../testdir dirtodelete/dirlinktodelete
Run Code Online (Sandbox Code Playgroud)
在这里,您可以看到测试文件和测试目录:
$ ls dirtodelete testdir
dirtodelete:
dirlinktodelete
testdir:
testfile
Run Code Online (Sandbox Code Playgroud)
然后运行commons-io deleteDirectory()或其他人发布的示例代码。它不仅删除目录,还删除正在删除的目录之外的测试文件。(它隐式地取消引用目录,并删除内容)。rm -r仅删除链接。您需要使用类似以下的方法删除已取消引用的文件:“查找-Ldirodelete -type f -exec rm {} \;”。
$ ls dirtodelete testdir
ls: cannot access dirtodelete: No such file or directory
testdir:Run Code Online (Sandbox Code Playgroud)