Löschen Sie alle Dateien im Verzeichnis (aber nicht im Verzeichnis) - eine Einzeilerlösung

201

Ich möchte alle Dateien im ABC-Verzeichnis löschen.

Wenn ich es versucht FileUtils.deleteDirectory(new File("C:/test/ABC/"));habe, wird auch der Ordner ABC gelöscht.

Gibt es eine Einzeilerlösung, bei der ich Dateien innerhalb eines Verzeichnisses löschen kann, jedoch nicht eines Verzeichnisses?

Fahim Parkar
quelle
2
Dies liegt daran, dass .deleteDirectory (auch der Name impliziert dies) zum Löschen von Verzeichnissen verwendet wird. Es erhält das Verzeichnis, in dem es sich befindet, wenn die Datei kein Verzeichnis ist.
user1534664
Suchen Sie nach anderen Funktionen in der FileUtils-Klasse, die Dateien anstelle von Verzeichnissen löschen.
user1534664
1
Warum brauchen Sie speziell einen Einzeiler? Leistung kann nicht das Kriterium sein, da jede Bibliotheksmethode eines Drittanbieters dies nur rekursiv tut. Es würde Ihnen also die gleiche Leistung bringen?
Rohit Jain
1
Sie können das Verzeichnis löschen und anschließend neu erstellen. Wir haben festgestellt, dass die Verwendung rm -rf directory; mkdir directoryschneller ist als die Verwendung FileUtils.cleanDirectory.
Joshua Pinter

Antworten:

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

FileUtils.cleanDirectory(directory); 

Diese Methode ist in derselben Datei verfügbar. Dadurch werden auch alle Unterordner und Dateien unter ihnen rekursiv gelöscht.

Docs: org.apache.commons.io.FileUtils.cleanDirectory

Reddy
quelle
49
Schön, auch um zu verhindern, dass die Leute das nachschlagen müssen; Hier ist der Import: import org.apache.commons.io.FileUtils;
Paul Gregoire
5
Ich muss noch nachsehen, warum der Import nicht gefunden werden kann. Es ist, weil man es von apache.org herunterladen muss .
Tomáš Zato - Wiedereinsetzung Monica
hübsche Lösung. Überprüfen Sie diese Bibliothek von gradle: kompilieren Sie "commons-io: commons-io: +"
Leo Nguyen
1
Gradle-Abhängigkeit - Kompilierungsgruppe: 'commons-io', Name: 'commons-io', Version: '2.5'.
Jaydev
Beachten Sie, dass das Anrufen rm -rf directoryviel effizienter war als das Verwenden FileUtils.cleanDirectory.
Joshua Pinter
267

Meinst du wie?

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

Dadurch werden nur Dateien gelöscht, keine Verzeichnisse.

Peter Lawrey
quelle
65
Dies ist definitiv die bessere Antwort, da keine externe Bibliothek verwendet wird!
AlexWien
10
@amar aber selbst dann: Wenn es eine Standardmethode gibt, gibt es absolut keinen Grund, eine externe Methode zu verwenden, die dasselbe tut. Eines Tages möchte er möglicherweise die Bibliothek loswerden, oder die Bibliothek wird nicht mehr unterstützt oder darf die Bibliothek aus Lizenzgründen usw. nicht mehr verwenden. (Dies alles ist möglicherweise kein Problem für diese bestimmte Bibliothek, gilt jedoch für viele andere)
AlexWien
10
Dadurch wird nicht alles gelöscht, wenn sich Unterverzeichnisse im Stammverzeichnis "dir" befinden.
Tiago
2
@TiagoT True, dies löscht keine Unterverzeichnisse, die nicht leer sind.
Peter Lawrey
4
for(File file: dir.listFiles())ist wahrscheinlich gemeint als .... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.
62

Peter Lawreys Antwort ist großartig, weil sie einfach ist und nicht von etwas Besonderem abhängt, und so sollten Sie es tun. Wenn Sie etwas benötigen, das auch Unterverzeichnisse und deren Inhalt entfernt, verwenden Sie die Rekursion:

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

Ändern Sie Folgendes, um Unterverzeichnisse und deren Inhalt (Teil Ihrer Frage) zu schonen:

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

Oder, weil Sie eine einzeilige Lösung wollten:

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

Die Verwendung einer externen Bibliothek für eine solche triviale Aufgabe ist keine gute Idee, es sei denn, Sie benötigen diese Bibliothek ohnehin für etwas anderes. In diesem Fall ist es vorzuziehen, vorhandenen Code zu verwenden. Sie scheinen die Apache-Bibliothek ohnehin zu verwenden, verwenden Sie also ihre FileUtils.cleanDirectory()Methode.

ChrisB
quelle
1
Wenn andererseits niemand als erster die externe Bibliothek verwendet, ist es weniger wahrscheinlich, dass andere ein ähnliches Verhalten in dieser externen Bibliothek erwarten, und weniger wahrscheinlich, dass sie dort suchen ... haben wir nicht genug Hier draußen nicht erfunden? Wenn die Bibliothek zusammenhängend ist und einfach zu meinem Projekt hinzugefügt werden kann, ziehe ich es fast immer vor, die Bibliothek hinzuzufügen.
JB Rainsberger
33

Java 8 Stream

Dadurch werden nur Dateien aus ABC gelöscht (Unterverzeichnisse bleiben unberührt):

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

Dadurch werden nur Dateien aus ABC (und Unterverzeichnissen) gelöscht :

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

^ Diese Version erfordert die Behandlung der IOException

Nichtlineare Frucht
quelle
1
Der zweite löscht nicht die Unterverzeichnisse (getestet)
edwise
1
@edwise Ja, es werden alle Dateien aus ABC und alle Dateien aus den Unterverzeichnissen gelöscht. Das Englisch ist ein wenig mehrdeutig.
Nichtlineare
11

Oder um dies in Java 8 zu verwenden:

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

Schade, dass die Ausnahmebehandlung so umfangreich ist, sonst wäre es ein Einzeiler ...

Christian Ullenboom
quelle
Wie wissen Sie , dass Datei IS eine Datei tatsächlich und kein Verzeichnis?
Stephan
1
Es löscht auch Verzeichnis, so ist es keine Lösung für das Problem aus dem Thema
Marx
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");
} }  }}
Manbumihu Manavan
quelle
2

Eine weitere Java 8 Stream-Lösung zum Löschen des gesamten Inhalts eines Ordners, einschließlich der Unterverzeichnisse, jedoch nicht des Ordners selbst.

Verwendung:

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

und der Code:

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

Das Problem bei jeder Stream-Lösung mit Files.walk oder Files.delete besteht darin, dass diese Methoden eine IOException auslösen, die in Streams nur schwer zu handhaben ist.

Ich habe versucht, eine möglichst präzise Lösung zu finden.

entführen
quelle
Anstatt eine Null in der Walk-Funktion zurückzugeben, ist es besser, einen leeren Stream (Stream.empty ()) zurückzugeben. Es ist sauberer und die Funktion gibt immer einen Stream zurück. Null sollte nach Möglichkeit vermieden werden.
Kaba713
Danke, ich habe die Antwort mit Ihrem Vorschlag verbessert
Entführung
2

Um alle Dateien aus dem Verzeichnis zu löschen, sagen Sie "C: \ Beispiel".

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();
    }
}
Mahesh Narwade
quelle
2

rm -rfwar viel performanter als FileUtils.cleanDirectory.

Keine Einzeiler-Lösung, aber nach umfangreichem Benchmarking stellten wir fest, dass die Verwendung rm -rfum ein Vielfaches schneller war als die Verwendung FileUtils.cleanDirectory.

Wenn Sie ein kleines oder einfaches Verzeichnis haben, spielt das natürlich keine Rolle, aber in unserem Fall hatten wir mehrere Gigabyte und tief verschachtelte Unterverzeichnisse, in denen es über 10 Minuten FileUtils.cleanDirectoryund nur 1 Minute dauern würde rm -rf.

Hier ist unsere grobe Java-Implementierung, um dies zu tun:

// 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;

}

Es lohnt sich zu versuchen, wenn Sie mit großen oder komplexen Verzeichnissen arbeiten.

Joshua Pinter
quelle
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);
                }
            }
        }
    }
}

Wenn Sie alle Dateien löschen möchten, entfernen Sie

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

Aussage, es wird funktionieren.

Mahesh
quelle
0

Ich denke, das wird funktionieren (basierend auf der vorherigen Antwort von 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);

Prost!

Dansouza
quelle