删除目录中的所有文件(但不删除目录)-一种班轮解决方案


201

我想删除ABC目录中的所有文件。

当我尝试使用FileUtils.deleteDirectory(new File("C:/test/ABC/"));它时,还会删除文件夹ABC。

是否有一种划线员解决方案,我可以删除目录中的文件,但不能删除目录中的文件?


2
那是因为.deleteDirectory(即使名称暗示它)也用于删除目录。如果文件不是目录,它将获取它所在的目录。
user1534664 '11

尝试在FileUtils类内查找其他函数,该函数删除文件而不是目录文件。
user1534664 '11


1
为什么您特别需要单线?性能不能成为标准,因为任何第三方库方法都只能递归地执行该操作。这样可以给您相同的性能吗?
罗希特·贾因

1
您可以做的一件事是删除目录,然后重新创建它。我们发现使用rm -rf directory; mkdir directory比使用更快FileUtils.cleanDirectory
约书亚·品特

Answers:


362
import org.apache.commons.io.FileUtils;

FileUtils.cleanDirectory(directory); 

在同一文件中有此方法。这还将递归删除其下的所有子文件夹和文件。

文件: org.apache.commons.io.FileUtils.cleanDirectory


49
不错,也可以防止人们不得不看这个;这是导入:import org.apache.commons.io.FileUtils;
Paul Gregoire 2013年

5
我仍然必须查明为什么找不到导入。这是因为必须从apache.org下载它
托马什Zato -恢复莫妮卡

漂亮的解决方案。通过gradle检查此lib:编译“ commons-io:commons-io:+”
Leo Nguyen

1
Gradle依赖性 -编译组:'commons-io',名称:'commons-io',版本:'2.5'。
Jaydev '16

请注意,我们发现调用rm -rf directory比使用更为有效FileUtils.cleanDirectory
约书亚·品特

267

你是说喜欢吗?

for(File file: dir.listFiles()) 
    if (!file.isDirectory()) 
        file.delete();

这只会删除文件,不会删除目录。


65
这是definitley更好的答案,因为它不使用外部库!
AlexWien

10
@amar,但即使这样:当有一种标准方法时,绝对没有理由使用做相同事情的外部方法。有一天,他可能想摆脱该库,或者该库不再受支持,或者由于许可原因而被禁止使用该库,等等。(这对于该特定库可能不是问题,但适用于其他很多))
AlexWien

10
如果您在根“ dir”目录中有子目录,则将无法删除所有内容。
Tiago

2
@TiagoT是的,这不会删除不为空的子目录。
彼得·劳瑞

4
for(File file: dir.listFiles())大概的意思是... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
哈特穆特·体育

62

彼得·劳瑞(Peter Lawrey)的回答很好,因为它很简单,并且不依赖任何特殊内容,这是您应该这样做的方式。如果您还需要删除子目录及其内容的内容,请使用递归:

void purgeDirectory(File dir) {
    for (File file: dir.listFiles()) {
        if (file.isDirectory())
            purgeDirectory(file);
        file.delete();
    }
}

要保留子目录及其内容(问题的一部分),请进行以下修改:

void purgeDirectoryButKeepSubDirectories(File dir) {
    for (File file: dir.listFiles()) {
        if (!file.isDirectory())
            file.delete();
    }
}

或者,由于您需要一种解决方案:

for (File file: dir.listFiles())
    if (!file.isDirectory())
        file.delete();

除非您仍然需要此库来执行其他操作,否则将外部库用于此类琐碎的任务不是一个好主意,在这种情况下,最好使用现有代码。无论如何,您似乎都在使用Apache库,因此请使用其FileUtils.cleanDirectory()方法。


1
另一方面,如果没有人是第一个使用外部库的人,那么其他人不太可能在该外部库中找到类似的行为,也不太可能看到他们在外部库中...我们没有足够的资源吗?不是在这里发明的吗?如果该库具有凝聚力并且易于添加到我的项目中,那么我几乎总是喜欢添加该库。
JB Rainsberger'8

33

Java 8流

这仅从ABC删除文件(未修改子目录):

Arrays.stream(new File("C:/test/ABC/").listFiles()).forEach(File::delete);

这只会从ABC(和子目录)中删除文件:

Files.walk(Paths.get("C:/test/ABC/"))
                .filter(Files::isRegularFile)
                .map(Path::toFile)
                .forEach(File::delete);

^此版本需要处理IOException


1
第二个不删除子目录(已测试)
edwise

1
@edwise是,它将删除ABC中的所有文件以及子目录中的所有文件。英语有点含糊。
NonlinearFruit

11

或在Java 8中使用它:

try {
  Files.newDirectoryStream( directory ).forEach( file -> {
    try { Files.delete( file ); }
    catch ( IOException e ) { throw new UncheckedIOException(e); }
  } );
}
catch ( IOException e ) {
  e.printStackTrace();
}

可惜的是,异常处理是如此庞大,否则它将是单线的……


你怎么知道这个文件IS文件实际上并没有一个目录?
Stephan

1
它还会删除目录,所以这不是解决主题问题的方法
马克思

5
public class DeleteFile {
    public static void main(String[] args) {
        String path="D:\test"; 
        File file = new File(path);
        File[] files = file.listFiles(); 
        for (File f:files) 
        {if (f.isFile() && f.exists) 
            { f.delete();
system.out.println("successfully deleted");
            }else{
system.out.println("cant delete a file due to open or error");
} }  }}

2

另一个Java 8 Stream解决方案,用于删除文件夹的所有内容(包括子目录,但不删除文件夹本身)。

用法:

Path folder = Paths.get("/tmp/folder");
CleanFolder.clean(folder);

和代码:

public interface CleanFolder {
    static void clean(Path folder) throws IOException {

        Function<Path, Stream<Path>> walk = p -> {
            try { return Files.walk(p);
        } catch (IOException e) {
            return Stream.empty();
        }};

        Consumer<Path> delete = p -> {
            try {
                Files.delete(p);
            } catch (IOException e) {
            }
        };

        Files.list(folder)
            .flatMap(walk)
            .sorted(Comparator.reverseOrder())
            .forEach(delete);
    }
}

每个涉及Files.walk或Files.delete的流解决方案的问题在于,这些方法抛出IOException,这在流中很难处理。

我试图创建一个尽可能简洁的解决方案。


与其在walk函数中返回null,不如返回一个空流(Stream.empty())更好。它更干净,该函数始终返回流。尽可能避免为空。
kaba713

谢谢,我根据您的建议改善了答案
劫持

2

要从目录中删除所有文件,请说“ C:\ Example”

File file = new File("C:\\Example");      
String[] myFiles;    
if (file.isDirectory()) {
    myFiles = file.list();
    for (int i = 0; i < myFiles.length; i++) {
        File myFile = new File(file, myFiles[i]); 
        myFile.delete();
    }
}

2

rm -rf很多比更好的性能FileUtils.cleanDirectory

不是单线解决方案,而是经过广泛的基准测试后,我们发现使用的rm -rf速度比使用的速度快好几倍FileUtils.cleanDirectory

当然,如果您有一个小型目录或简单目录,都没关系,但是在我们的例子中,我们有多个GB和深嵌套的子目录,使用时将花费10分钟以上,FileUtils.cleanDirectory而使用则仅需要1分钟rm -rf

这是我们的粗略Java实现:

// Delete directory given and all subdirectories and files (i.e. recursively).
//
static public boolean clearDirectory( File file ) throws IOException, InterruptedException {

    if ( file.exists() ) {

        String deleteCommand = "rm -rf " + file.getAbsolutePath();
        Runtime runtime = Runtime.getRuntime();

        Process process = runtime.exec( deleteCommand );
        process.waitFor();

        file.mkdirs(); // Since we only want to clear the directory and not delete it, we need to re-create the directory.

        return true;
    }

    return false;

}

如果您要处理大型或复杂目录,则值得尝试。


1
package com;
import java.io.File;
public class Delete {
    public static void main(String[] args) {

        String files; 
        File file = new File("D:\\del\\yc\\gh");
        File[] listOfFiles = file.listFiles(); 
        for (int i = 0; i < listOfFiles.length; i++) 
        {
            if (listOfFiles[i].isFile()) 
            {
                files = listOfFiles[i].getName();
                System.out.println(files);
                if(!files.equalsIgnoreCase("Scan.pdf"))
                {
                    boolean issuccess=new File(listOfFiles[i].toString()).delete();
                    System.err.println("Deletion Success "+issuccess);
                }
            }
        }
    }
}

如果要删除所有文件,请删除

if(!files.equalsIgnoreCase("Scan.pdf"))

声明它将起作用。


0

我认为这会起作用(基于NonlinearFruit先前的答案):

Files.walk(Paths.get("C:/test/ABC/"))
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .filter(item -> !item.getPath().equals("C:/test/ABC/"))
                .forEach(File::delete);

干杯!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.