Usuń wszystkie pliki w katalogu (ale nie w katalogu) - jedno rozwiązanie liniowe


201

Chcę usunąć wszystkie pliki z katalogu ABC.

Kiedy próbowałem z FileUtils.deleteDirectory(new File("C:/test/ABC/"));tym, usuwa również folder ABC.

Czy istnieje jedno rozwiązanie liniowe, w którym mogę usuwać pliki z katalogu, ale nie z katalogu?


2
Dzieje się tak, ponieważ .deleteDirectory (nawet nazwa wskazuje na to) służy do usuwania katalogu. Otrzyma katalog, w którym się znajduje, jeśli plik nie jest katalogiem.
user1534664,

Spróbuj poszukać innych funkcji w klasie FileUtils, które usuwają pliki zamiast katalogów.
user1534664,


1
Dlaczego konkretnie potrzebujesz jednej wkładki? Wydajność nie może być kryterium, ponieważ każda metoda biblioteczna innej firmy zrobi to tylko rekurencyjnie. Czyli dałbyś taką samą wydajność?
Rohit Jain

1
Jedną rzeczą, którą możesz zrobić, to usunąć katalog, a następnie ponownie go utworzyć. Odkryliśmy, że używanie rm -rf directory; mkdir directorybyło szybsze niż używanie FileUtils.cleanDirectory.
Joshua Pinter

Odpowiedzi:


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

FileUtils.cleanDirectory(directory); 

Ta metoda jest dostępna w tym samym pliku. Spowoduje to również rekurencyjne usunięcie wszystkich podfolderów i plików pod nimi.

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


49
Fajny, również po to, by ludzie nie musieli tego sprawdzać; oto import: import org.apache.commons.io.FileUtils;
Paul Gregoire,

5
Nadal muszę sprawdzić, dlaczego nie można znaleźć importu. To dlatego, że należy go pobrać z apache.org .
Tomáš Zato - Przywróć Monikę

ładne rozwiązanie. Sprawdź tę bibliotekę według gradle: compile "commons-io: commons-io: +"
Leo Nguyen

1
Zależność stopniowa - grupa kompilacji: „commons-io”, nazwa: „commons-io”, wersja: „2.5”.
Jaydev,

Uwaga: stwierdziliśmy, że dzwonienie rm -rf directorybyło znacznie wydajniejsze niż używanie FileUtils.cleanDirectory.
Joshua Pinter

267

Masz na myśli?

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

Spowoduje to jedynie usunięcie plików, a nie katalogów.


65
Jest to zdecydowanie lepsza odpowiedź, ponieważ nie korzysta z zewnętrznej biblioteki lib!
AlexWien,

10
@amar, ale nawet wtedy: gdy istnieje standardowa metoda, nie ma absolutnie żadnego powodu, aby używać zewnętrznego, który robi to samo. Pewnego dnia może chcieć się pozbyć biblioteki lub biblioteka nie jest już obsługiwana lub nie wolno jej używać z powodów związanych z licencją itp. (To może nie być problem dla tej konkretnej biblioteki, ale dotyczy wiele innych)
AlexWien,

10
Nie spowoduje to usunięcia wszystkiego, jeśli masz podkatalogi w katalogu głównym „dir”.
Tiago,

2
@TiagoT Prawda, nie spowoduje to usunięcia podkatalogów, które nie są puste.
Peter Lawrey,

4
for(File file: dir.listFiles())jest prawdopodobnie oznaczony jako ... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.

62

Odpowiedź Petera Lawreya jest świetna, ponieważ jest prosta i nie zależy od niczego specjalnego, i tak właśnie powinieneś to zrobić. Jeśli potrzebujesz czegoś, co usuwa również podkatalogi i ich zawartość, użyj rekurencji:

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

Aby zaoszczędzić podkatalogi i ich zawartość (część pytania), zmodyfikuj w następujący sposób:

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

Lub, ponieważ chciałeś rozwiązania w jednym wierszu:

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

Użycie biblioteki zewnętrznej do tak trywialnego zadania nie jest dobrym pomysłem, chyba że i tak potrzebujesz tej biblioteki do czegoś innego, w którym to przypadku lepiej jest użyć istniejącego kodu. Wygląda na to, że i tak używasz biblioteki Apache, więc użyj jej FileUtils.cleanDirectory()metody.


1
Z drugiej strony, jeśli nikt nie użyje biblioteki zewnętrznej jako pierwszy, wówczas jest mniej prawdopodobne, że inni będą oczekiwać podobnego zachowania w tej bibliotece zewnętrznej, a rzadziej będą tam szukać ... nie mamy dość Nie wynaleziono tutaj? Jeśli biblioteka jest spójna i łatwa do dodania do mojego projektu, to prawie zawsze wolę dodawać bibliotekę.
JB Rainsberger,

33

Strumień Java 8

Spowoduje to usunięcie tylko plików z ABC (podkatalogi pozostają nietknięte):

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

Spowoduje to usunięcie tylko plików z ABC (i podkatalogów):

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

^ Ta wersja wymaga obsługi wyjątku IOException


1
Drugi nie usuwa podkatalogów (testowane)
edwise

1
@edwise Tak, usuwa wszystkie pliki z ABC i wszystkie pliki z podkatalogów. Angielski jest trochę dwuznaczny.
NielinioweOwoc

11

Lub użyć tego w Javie 8:

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

Szkoda, że ​​obsługa wyjątków jest tak nieporęczna, w przeciwnym razie byłaby to jedna linijka ...


Skąd wiesz, że ten plik jest plikiem, a nie katalogiem?
Stephan

1
Usuwa także katalog, więc nie jest to rozwiązanie problemu z tematu
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");
} }  }}

2

Kolejne rozwiązanie Java 8 Stream do usuwania całej zawartości folderu, w tym podkatalogów, ale nie samego folderu.

Stosowanie:

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

i kod:

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

Problem z każdym rozwiązaniem strumienia obejmującym Files.walk lub Files.delete polega na tym, że metody te generują wyjątek IOException, który jest trudny w obsłudze w strumieniach.

Próbowałem stworzyć rozwiązanie, które jest bardziej zwięzłe, jak to możliwe.


Zamiast zwracania wartości null w funkcji walk lepiej byłoby zwrócić pusty strumień (Stream.empty ()). Jest czystszy, a funkcja zawsze zwraca strumień. W miarę możliwości należy unikać wartości zerowej.
kaba713

Dzięki, poprawiłem odpowiedź twoją sugestią
porwanie

2

Aby usunąć wszystkie pliki z katalogu, powiedz „C: \ Przykład”

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 -rfbył znacznie bardziej wydajny niż FileUtils.cleanDirectory.

Nie jedno rozwiązanie liniowe, ale po szeroko zakrojonych testach porównawczych stwierdziliśmy, że używanie rm -rfbyło wielokrotnie szybsze niż używanie FileUtils.cleanDirectory.

Oczywiście, jeśli masz mały lub prosty katalog, nie będzie to miało znaczenia, ale w naszym przypadku mieliśmy wiele gigabajtów i głęboko zagnieżdżone podkatalogi, w których zajęłoby to ponad 10 minut FileUtils.cleanDirectoryi tylko 1 minutę rm -rf.

Oto nasza przybliżona implementacja Java, aby to zrobić:

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

}

Warto spróbować, jeśli masz do czynienia z dużymi lub złożonymi katalogami.


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

Jeśli chcesz usunąć wszystkie pliki, usuń

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

oświadczenie będzie działać.


0

Myślę, że to zadziała (na podstawie poprzedniej odpowiedzi 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);

Twoje zdrowie!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.