Eliminar todos los archivos en el directorio (pero no en el directorio): una solución de línea

201

Quiero eliminar todos los archivos dentro del directorio ABC.

Cuando lo probé FileUtils.deleteDirectory(new File("C:/test/ABC/"));, también elimina la carpeta ABC.

¿Existe una solución de línea única donde puedo eliminar archivos dentro del directorio pero no el directorio?

Fahim Parkar
fuente
2
Eso es porque .deleteDirectory (incluso el nombre lo implica) se usa para eliminar directorios. Obtendrá el directorio en el que se encuentra si el archivo no es un directorio.
user1534664
Intente buscar otras funciones dentro de la clase FileUtils, que eliminan archivos en lugar de directorios.
user1534664
1
¿Por qué necesitas específicamente una línea? El rendimiento no puede ser el criterio, porque cualquier método de biblioteca de terceros solo lo hará de forma recursiva. ¿Entonces te daría el mismo rendimiento?
Rohit Jain
1
Una cosa que puede hacer es eliminar el directorio y luego volver a crearlo. Descubrimos que usar rm -rf directory; mkdir directoryera más rápido que usar FileUtils.cleanDirectory.
Joshua Pinter el

Respuestas:

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

FileUtils.cleanDirectory(directory); 

Hay este método disponible en el mismo archivo. Esto también eliminará de forma recursiva todas las subcarpetas y archivos debajo de ellas.

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

Reddy
fuente
49
Agradable, también para evitar que las personas tengan que buscar esto; aquí está la importación: import org.apache.commons.io.FileUtils;
Paul Gregoire
55
Todavía tengo que buscar por qué no se puede encontrar la importación. Es porque uno debe descargarlo de apache.org .
Tomáš Zato - Restablece a Monica el
Bonita solución. Comprueba esta lib por gradle: compila "commons-io: commons-io: +"
Leo Nguyen
1
Dependencia de Gradle : grupo de compilación: 'commons-io', nombre: 'commons-io', versión: '2.5'.
Jaydev
Tenga en cuenta que encontramos que llamar rm -rf directoryera mucho más eficiente que usar FileUtils.cleanDirectory.
Joshua Pinter el
267

¿Quieres decir como?

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

Esto solo eliminará archivos, no directorios.

Peter Lawrey
fuente
65
Esta es definitivamente la mejor respuesta, ya que no utiliza una biblioteca externa.
AlexWien
10
@amar pero aun así: cuando hay un método estándar, no hay absolutamente ninguna razón para usar uno externo que haga lo mismo. Un día puede querer deshacerse de la biblioteca, o la biblioteca ya no es compatible, o no se le permite usar la biblioteca por razones de licencia, etc. (Todo esto podría no ser un problema para esta biblioteca específica, pero se aplica a muchos otros)
AlexWien
10
Esto no podrá eliminar todo si tiene subdirectorios dentro del directorio raíz "dir".
Tiago
2
@TiagoT Cierto, esto no eliminará los subdirectorios que no estén vacíos.
Peter Lawrey
44
for(File file: dir.listFiles())probablemente se entiende como ... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.
62

La respuesta de Peter Lawrey es excelente porque es simple y no depende de nada especial, y es la forma en que debe hacerlo. Si necesita algo que elimine los subdirectorios y sus contenidos también, use la recursividad:

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

Para ahorrar subdirectorios y sus contenidos (parte de su pregunta), modifique de la siguiente manera:

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

O, como quería una solución de una línea:

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

Usar una biblioteca externa para una tarea tan trivial no es una buena idea a menos que necesite esta biblioteca para otra cosa de todos modos, en cuyo caso es preferible usar el código existente. Parece que está utilizando la biblioteca Apache de todos modos, así que use su FileUtils.cleanDirectory()método.

ChrisB
fuente
1
Por otro lado, si nadie es el primero en usar la biblioteca externa, entonces es menos probable que otros esperen encontrar un comportamiento similar en esa biblioteca externa, y menos probable que busquen allí ... ¿no tenemos suficiente ¿No inventado aquí afuera? Si la biblioteca es coherente y fácil de agregar a mi proyecto, casi siempre prefiero agregar la biblioteca.
JB Rainsberger
33

Java 8 Stream

Esto elimina solo archivos de ABC (los subdirectorios están intactos):

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

Esto elimina solo archivos de ABC (y subdirectorios):

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

^ Esta versión requiere el manejo de la IOException

Fruta no lineal
fuente
1
El segundo no elimina los subdirectorios (probado)
edwise
1
@edwise Sí, elimina todos los archivos de ABC y todos los archivos de los subdirectorios. El inglés es un poco ambiguo.
NonlinearFruit
11

O para usar esto en Java 8:

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

Es una lástima que el manejo de excepciones sea tan voluminoso, de lo contrario sería una frase ...

Christian Ullenboom
fuente
¿Cómo sabes que ese archivo ES un archivo en realidad y no un directorio?
Stephan
1
También elimina el directorio, por lo que no es una solución al problema del tema
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
fuente
2

Otra solución Java 8 Stream para eliminar todo el contenido de una carpeta, incluidos los subdirectorios, pero no la carpeta en sí.

Uso:

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

y el código:

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

El problema con cada solución de flujo que involucra Files.walk o Files.delete es que estos métodos arrojan IOException, que son difíciles de manejar en los flujos.

Intenté crear una solución lo más concisa posible.

secuestrar
fuente
En lugar de devolver un valor nulo en la función Walk, sería mejor devolver un flujo vacío (Stream.empty ()). Es más limpio y la función siempre devuelve una secuencia. Nulo debe evitarse cuando sea posible.
kaba713
Gracias, mejoré la respuesta con su sugerencia
secuestro
2

Para eliminar todos los archivos del directorio, diga "C: \ Ejemplo"

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
fuente
2

rm -rffue mucho más eficiente queFileUtils.cleanDirectory .

No es una solución única, pero después de una evaluación comparativa exhaustiva, descubrimos que usar rm -rfera varias veces más rápido que usarFileUtils.cleanDirectory .

Por supuesto, si tiene un directorio pequeño o simple, no importará, pero en nuestro caso teníamos varios gigabytes y subdirectorios profundamente anidados donde tomaría más de 10 minutos FileUtils.cleanDirectoryy solo 1 minuto conrm -rf .

Aquí está nuestra implementación aproximada de Java para hacer eso:

// 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 intentarlo si se trata de directorios grandes o complejos.

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

Si desea eliminar todos los archivos, elimine

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

declaración funcionará.

Mahesh
fuente
0

Creo que esto funcionará (basado en la respuesta anterior de 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);

¡Salud!

dansouza
fuente