Elimina tutti i file nella directory (ma non nella directory) - una soluzione di linea


201

Voglio eliminare tutti i file nella directory ABC.

Quando ho provato con FileUtils.deleteDirectory(new File("C:/test/ABC/"));esso cancella anche la cartella ABC.

Esiste una soluzione di linea in cui posso eliminare i file all'interno della directory ma non nella directory?


2
Questo perché .deleteDirectory (anche il nome lo implica) viene utilizzato per eliminare le directory. Otterrà la directory in cui si trova se il file non è una directory.
user1534664

Prova a cercare altre funzioni all'interno della classe FileUtils, che eliminano i file anziché quelli della directory.
user1534664


1
Perché hai bisogno specificamente di un one-liner? Le prestazioni non possono essere i criteri, poiché qualsiasi metodo di libreria di terze parti lo farà solo in modo ricorsivo. Quindi ti darebbe la stessa performance?
Rohit Jain,

1
Una cosa che puoi fare è cancellare la directory e poi ricrearla. Abbiamo scoperto che l'utilizzo rm -rf directory; mkdir directoryera più veloce dell'uso FileUtils.cleanDirectory.
Joshua Pinter,

Risposte:


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

FileUtils.cleanDirectory(directory); 

C'è questo metodo disponibile nello stesso file. Ciò eliminerà anche in modo ricorsivo tutte le sottocartelle e i file sottostanti.

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


49
Bello, anche per impedire alle persone di cercare questo; ecco l'importazione: import org.apache.commons.io.FileUtils;
Paul Gregoire,

5
Devo ancora cercare perché non è possibile trovare l'importazione. È perché bisogna scaricarlo da apache.org .
Tomáš Zato - Ripristina Monica il

bella soluzione. Controlla questa lib in base al grado: compila "commons-io: commons-io: +"
Leo Nguyen,

1
Dipendenza dal grado - gruppo di compilazione: 'commons-io', nome: 'commons-io', versione: '2.5'.
Jaydev,

Nota, abbiamo scoperto che chiamare rm -rf directoryera molto più efficiente dell'uso FileUtils.cleanDirectory.
Joshua Pinter,

267

Vuoi dire come?

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

Questo eliminerà solo i file, non le directory.


65
Questa è sicuramente la risposta migliore, dal momento che non utilizza una libreria esterna!
AlexWien,

10
@amar ma anche allora: quando esiste un metodo standard non c'è assolutamente motivo di usarne uno esterno che faccia la stessa cosa. Un giorno potrebbe voler sbarazzarsi della lib, o la lib non è più supportata o non è consentito utilizzare la lib per motivi di licenza, ecc. (Questo potrebbe non essere un problema per questa specifica lib, ma si applica a molti altri)
AlexWien,

10
Questo non eliminerà tutto se ci sono sottodirectory nella directory "dir" di root.
Tiago,

2
@TiagoT True, questo non eliminerà le sottodirectory che non sono vuote.
Peter Lawrey,

4
for(File file: dir.listFiles())è probabilmente inteso come .... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.

62

La risposta di Peter Lawrey è eccezionale perché è semplice e non dipende da nulla di speciale, ed è il modo in cui dovresti farlo. Se hai bisogno di qualcosa che rimuova anche le sottodirectory e il loro contenuto, usa la ricorsione:

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

Per risparmiare le sottodirectory e il loro contenuto (parte della tua domanda), modifica come segue:

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

Oppure, poiché volevi una soluzione a una riga:

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

L'uso di una libreria esterna per un compito così banale non è una buona idea a meno che non sia necessaria questa libreria per qualcos'altro, nel qual caso è preferibile utilizzare il codice esistente. Sembra che tu stia usando comunque la libreria Apache, quindi usa il suo FileUtils.cleanDirectory()metodo.


1
D'altra parte, se nessuno è il primo a utilizzare la libreria esterna, allora è meno probabile che altri si aspettino di trovare un comportamento simile in quella libreria esterna e meno probabile che guarderanno lì ... non ne abbiamo abbastanza Non inventato qui fuori? Se la libreria è coerente e facile da aggiungere al mio progetto, preferisco quasi sempre aggiungere la libreria.
JB Rainsberger,

33

Java 8 Stream

Questo elimina solo i file da ABC (le sottodirectory non sono state toccate):

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

Questo elimina solo i file da ABC (e sottodirectory):

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

^ Questa versione richiede la gestione di IOException


1
Il secondo non cancella le sottodirectory (testate)
edwise

1
@edwise Sì, elimina tutti i file dalla ABC e tutti i file dalle sottodirectory. L'inglese è un po 'ambiguo.
NonlinearFruit

11

O per usarlo in Java 8:

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

È un peccato che la gestione delle eccezioni sia così ingombrante, altrimenti sarebbe un one-liner ...


Come fai a sapere che il file È effettivamente un file e non una directory?
Stephan,

1
Elimina anche la directory, quindi non è una soluzione al problema dall'argomento
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

Un'altra soluzione Java 8 Stream per eliminare tutto il contenuto di una cartella, incluse le sottodirectory, ma non la cartella stessa.

Uso:

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

e il codice:

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

Il problema con ogni soluzione di flusso che coinvolge Files.walk o Files.delete è che questi metodi generano IOException che è una seccatura da gestire nei flussi.

Ho cercato di creare una soluzione il più concisa possibile.


Invece di restituire un null nella funzione walk, sarebbe meglio restituire un flusso vuoto (Stream.empty ()). È più pulito e la funzione restituisce sempre un flusso. Null dovrebbe essere evitato quando possibile.
Kaba713,

Grazie, ho migliorato la risposta con il tuo suggerimento
dirottare l'

2

Per cancellare tutti i file dalla directory dire "C: \ Esempio"

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 -rfera molto più performante di FileUtils.cleanDirectory.

Non una soluzione one-liner ma dopo un ampio benchmarking, abbiamo scoperto che l'utilizzo rm -rfera più volte più veloce dell'uso FileUtils.cleanDirectory.

Ovviamente, se hai una directory piccola o semplice, non importa, ma nel nostro caso avevamo più gigabyte e sottodirectory profondamente annidate dove ci sarebbero voluti più di 10 minuti FileUtils.cleanDirectorye solo 1 minuto con rm -rf.

Ecco la nostra approssimativa implementazione Java per farlo:

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

}

Vale la pena provare se hai a che fare con directory grandi o complesse.


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

Se si desidera eliminare tutti i file, rimuovere

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

dichiarazione funzionerà.


0

Penso che funzionerà (basato sulla risposta precedente di 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);

Saluti!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.