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?


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


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.


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.


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


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 ...


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

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.


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

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.


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á.


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!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.