Cómo eliminar una carpeta con archivos usando Java

104

Quiero crear y eliminar un directorio usando Java, pero no funciona.

File index = new File("/home/Work/Indexer1");
if (!index.exists()) {
    index.mkdir();
} else {
    index.delete();
    if (!index.exists()) {
        index.mkdir();
    }
}
Señor G
fuente
3
¿Qué pasó cuando lo intentaste?
Abimaran Kugathasan
¿Cuál es la pregunta?
Aniket Thakur
1
archivo de índice no eliminado.
Mr.G
1
Consulte Cómo eliminar un directorio en Java
Aniket Thakur
1
Desafortunadamente, @AniketThakur, ese enfoque seguirá enlaces simbólicos y eliminará archivos y directorios que pueden no haber sido previstos.
Hank Schultz

Respuestas:

99

Java no puede eliminar carpetas con datos. Debe eliminar todos los archivos antes de eliminar la carpeta.

Usa algo como:

String[]entries = index.list();
for(String s: entries){
    File currentFile = new File(index.getPath(),s);
    currentFile.delete();
}

¡Entonces deberías poder eliminar la carpeta usando Sin index.delete() probar!

Cemron
fuente
37
Esto no eliminará los subdirectorios que no estén vacíos.
Francesco Menzani
13
debes escribir un método recursivo o usar FileUtils.deleteDirectorycomo dijo @Francesco Menzani.
EN20
4
Ten mucho cuidado. Si index es un enlace simbólico a otro directorio, terminará borrando el contenido del otro directorio. Desafortunadamente, todavía no he encontrado una buena manera de detectar enlaces simbólicos en Windows en Java 6, aunque Java 7 proporciona Files.isSymbolicLink ().
Hank Schultz
1
Solución: envuelva este fragmento de código if (!index.delete()) {...}. Luego, si el índice es un enlace simbólico, se elimina independientemente de si parece que tiene contenido.
Hank Schultz
Esto lanzará una NullPointerException si hay una excepción de E / S mientras se lee el directorio. El código debe verificar si entrieses nulo.
mernst
178

Solo una frase.

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

Documentación aquí

Barry Knapp
fuente
13
mmm no. Se trata de una línea de una sola línea con una dependencia externa, que es algo importante a tener en cuenta. La única vez que usa una dependencia externa como esta es así de simple es cuando está haciendo un proyecto personal en el hogar, o cuando a su empresa realmente no le importa la posibilidad de ser demandada.
seekchengine27
11
@ seekchengine27 pero parece que la biblioteca está bajo Apache Commons, por lo que el riesgo de ser demandado es insignificante whitesourcesoftware.com/whitesource-blog/… .
simtim
1
@simtim te estás perdiendo el punto por completo. Una empresa nunca aprobará el uso de una biblioteca sin un equipo de abogados que analice primero los términos de uso y los acuerdos de usuario final, y cualquier otro documento legal asociado con la biblioteca. Alguien tiene que pagarles a esos abogados ... a veces nadie quiere, lo que significa que el desarrollador no puede usarlo. Cuanto más grande sea la empresa para la que trabaja, más burocracia tendrá que atravesar.
seekchengine27
19
@ seekchengine27 no, te estás perdiendo el punto por completo. Una empresa que necesita un ejército de abogados para permitir el uso de apache commons es la patología absoluta, y nada cerca de la norma en el mundo de las tecnologías de la información. Nunca escuché de nadie que tenga tales problemas y si usted tiene tales problemas, lo más probable es que tenga el acceso a SO bloqueado, por lo que la respuesta no será accesible para usted de todos modos.
9ilsdx 9rvj 0lo
94

Esto funciona, y aunque parece ineficaz omitir la prueba del directorio, no lo es: la prueba ocurre de inmediato en listFiles().

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            deleteDir(f);
        }
    }
    file.delete();
}

Actualizar, para evitar seguir enlaces simbólicos:

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            if (! Files.isSymbolicLink(f.toPath())) {
                deleteDir(f);
            }
        }
    }
    file.delete();
}
Jeff Learman
fuente
2
Resulta que hay un error en esto. Si otro proceso elimina los archivos durante el ciclo, puede causar una excepción que debe detectarse e ignorarse.
Jeff Learman
2
@ 9ilsdx9rvj0lo En lugar de ser sarcástico, quizás podría proporcionar una edición para manejar enlaces simbólicos. El OP no dijo nada sobre los enlaces simbólicos en su publicación. Simplemente creando y eliminando un directorio. Indique también las "muchas cosas que faltan". Ayudanos.
Perry Tew
@PerryTew No estoy siendo sarcástico. Solo estoy señalando que no estoy completamente de acuerdo con su comentario sobre que la respuesta es mejor porque no se están utilizando bibliotecas externas. No lo es. Hay una buena razón por la que la gente usa apache commons: no es necesario que programes nada tú mismo. Los enlaces simbólicos son solo un ejemplo de cosas que extrañará escribir todo desde cero.
9ilsdx 9rvj 0lo
2
No se trata de mejor / peor, sino de pros y contras. No depender de bibliotecas externas a veces es un beneficio significativo. Por supuesto, hay un beneficio significativo al usar software probado y verdadero. Depende del desarrollador equilibrar los problemas. Si hay errores distintos a los dos ya mencionados, ciertamente nos gustaría conocerlos.
Jeff Learman
31

Prefiero esta solución en java 8:

  Files.walk(pathToBeDeleted)
    .sorted(Comparator.reverseOrder())
    .map(Path::toFile)
    .forEach(File::delete);

Desde este sitio: http://www.baeldung.com/java-delete-directory

nirmal
fuente
2
Tenga en cuenta que esto puede tener problemas de escalabilidad, ya que crea la lista completa, crea una copia ordenada y luego itera sobre la copia ordenada. En los viejos tiempos, cuando la memoria no era inagotable, esto sería una muy mala idea. Es conciso pero tiene un costo en espacio (O (N) vs O (1)) y eficiencia (O (N log N) vs O (N)). Esto no importaría en la mayoría de los casos de uso.
Jeff Learman
Debería haber dicho "espacio O (N) vs O (profundidad)" arriba, donde la profundidad es la profundidad del árbol de directorios (comparando esta solución con las recursivas).
Jeff Learman
1
esto es elegante, funciona y no depende de bibliotecas externas. me encantó
Leo
¿No tiene esto el problema de las fugas en el manejo de archivos? Este ejemplo no cierra la secuencia devuelta por Files.walk(), que se indica explícitamente en los documentos de la API. Sé que si no cierra la secuencia devuelta por, Files.list()por ejemplo, puede quedarse sin identificadores y el programa se bloqueará. Consulte, por ejemplo, stackoverflow.com/q/36990053/421049 y stackoverflow.com/q/26997240/421049 .
Garret Wilson
23

Usando Apache Commons-IO, sigue una línea:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

Esto es (ligeramente) más eficaz que FileUtils.deleteDirectory.

JRA_TLL
fuente
grupo: 'commons-io', nombre: 'commons-io', versión: '2. +' - útil
mike rodent
10

Como se mencionó, Java no puede eliminar una carpeta que contiene archivos, así que primero elimine los archivos y luego la carpeta.

Aquí hay un ejemplo simple para hacer esto:

import org.apache.commons.io.FileUtils;



// First, remove files from into the folder 
FileUtils.cleanDirectory(folder/path);

// Then, remove the folder
FileUtils.deleteDirectory(folder/path);

O:

FileUtils.forceDelete(new File(destination));
Gavriel Cohen
fuente
9

Mi versión recursiva básica, trabajando con versiones anteriores de JDK:

public static void deleteFile(File element) {
    if (element.isDirectory()) {
        for (File sub : element.listFiles()) {
            deleteFile(sub);
        }
    }
    element.delete();
}
Pierre Lemée
fuente
2
Esto lanzará una NullPointerException si hay una excepción de E / S mientras se lee el directorio. El código debe verificar si listFiles()devuelve un valor nulo, en lugar de llamar isDirectory().
mernst
9

Ésta es la mejor solución para Java 7+:

public static void deleteDirectory(String directoryFilePath) throws IOException
{
    Path directory = Paths.get(directoryFilePath);

    if (Files.exists(directory))
    {
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>()
        {
            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException
            {
                Files.delete(path);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path directory, IOException ioException) throws IOException
            {
                Files.delete(directory);
                return FileVisitResult.CONTINUE;
            }
        });
    }
}
BullyWiiPlaza
fuente
6

Guava 21+ al rescate. Úselo solo si no hay enlaces simbólicos que señalen fuera del directorio para eliminar.

com.google.common.io.MoreFiles.deleteRecursively(
      file.toPath(),
      RecursiveDeleteOption.ALLOW_INSECURE
) ;

(Esta pregunta está bien indexada por Google, por lo que otras personas que usen Guava podrían estar felices de encontrar esta respuesta, incluso si es redundante con otras respuestas en otros lugares).

Laurent Caillette
fuente
4

Me gusta más esta solución. No utiliza una biblioteca de terceros, sino que utiliza NIO2 de Java 7.

/**
 * Deletes Folder with all of its content
 *
 * @param folder path to folder which should be deleted
 */
public static void deleteFolderAndItsContent(final Path folder) throws IOException {
    Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            if (exc != null) {
                throw exc;
            }
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}
Javo
fuente
3

Una opción más es utilizar el org.springframework.util.FileSystemUtilsmétodo relevante de Spring, que eliminará de forma recursiva todo el contenido del directorio.

File directoryToDelete = new File(<your_directory_path_to_delete>);
FileSystemUtils.deleteRecursively(directoryToDelete);

¡Eso hará el trabajo!

dZ.
fuente
2

En esto

index.delete();

            if (!index.exists())
               {
                   index.mkdir();
               }

estas llamando

 if (!index.exists())
                   {
                       index.mkdir();
                   }

después

index.delete();

Esto significa que está creando el archivo nuevamente después de eliminar File.delete () devuelve un valor booleano. Por lo tanto, si desea verificarlo, System.out.println(index.delete());si lo obtiene true, esto significa que el archivo se eliminó

File index = new File("/home/Work/Indexer1");
    if (!index.exists())
       {
             index.mkdir();
       }
    else{
            System.out.println(index.delete());//If you get true then file is deleted




            if (!index.exists())
               {
                   index.mkdir();// here you are creating again after deleting the file
               }




        }

de los comentarios que se dan a continuación, la respuesta actualizada es así

File f=new File("full_path");//full path like c:/home/ri
    if(f.exists())
    {
        f.delete();
    }
    else
    {
        try {
            //f.createNewFile();//this will create a file
            f.mkdir();//this create a folder
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
SpringLearner
fuente
2

Si tiene subcarpetas, encontrará problemas con las respuestas de Cemron. entonces deberías crear un método que funcione así:

private void deleteTempFile(File tempFile) {
        try
        {
            if(tempFile.isDirectory()){
               File[] entries = tempFile.listFiles();
               for(File currentFile: entries){
                   deleteTempFile(currentFile);
               }
               tempFile.delete();
            }else{
               tempFile.delete();
            }
        getLogger().info("DELETED Temporal File: " + tempFile.getPath());
        }
        catch(Throwable t)
        {
            getLogger().error("Could not DELETE file: " + tempFile.getPath(), t);
        }
    }
Panthro
fuente
2

Puede utilizar FileUtils.deleteDirectory . JAVA no puede eliminar las carpetas no vacías con File.delete () .

Issam Ressani
fuente
1

directry no puede simplemente eliminar si tiene los archivos, por lo que es posible que primero deba eliminar los archivos internos y luego el directorio

public class DeleteFileFolder {

public DeleteFileFolder(String path) {

    File file = new File(path);
    if(file.exists())
    {
        do{
            delete(file);
        }while(file.exists());
    }else
    {
        System.out.println("File or Folder not found : "+path);
    }

}
private void delete(File file)
{
    if(file.isDirectory())
    {
        String fileList[] = file.list();
        if(fileList.length == 0)
        {
            System.out.println("Deleting Directory : "+file.getPath());
            file.delete();
        }else
        {
            int size = fileList.length;
            for(int i = 0 ; i < size ; i++)
            {
                String fileName = fileList[i];
                System.out.println("File path : "+file.getPath()+" and name :"+fileName);
                String fullPath = file.getPath()+"/"+fileName;
                File fileOrFolder = new File(fullPath);
                System.out.println("Full Path :"+fileOrFolder.getPath());
                delete(fileOrFolder);
            }
        }
    }else
    {
        System.out.println("Deleting file : "+file.getPath());
        file.delete();
    }
}
Indranil.Bharambe
fuente
1

Puede realizar llamadas recursivas si existen subdirectorios

import java.io.File;

class DeleteDir {
public static void main(String args[]) {
deleteDirectory(new File(args[0]));
}

static public boolean deleteDirectory(File path) {
if( path.exists() ) {
  File[] files = path.listFiles();
  for(int i=0; i<files.length; i++) {
     if(files[i].isDirectory()) {
       deleteDirectory(files[i]);
     }
     else {
       files[i].delete();
     }
  }
}
return( path.delete() );
}
}
prem30488
fuente
1

podemos usar la spring-coredependencia;

boolean result = FileSystemUtils.deleteRecursively(file);
Kanagavelu Sugumar
fuente
1

La mayoría de las respuestas (incluso recientes) que hacen referencia a clases de JDK se basan en, File.delete()pero esa es una API defectuosa ya que la operación puede fallar silenciosamente.
La java.io.File.delete()documentación del método dice:

Tenga en cuenta que la java.nio.file.Filesclase define el deletemétodo para lanzar un IOExceptionarchivo cuando no se puede eliminar. Esto es útil para informar errores y diagnosticar por qué no se puede eliminar un archivo.

Como reemplazo, debe favorecer Files.delete(Path p) que arroje un IOExceptionmensaje de error.

El código real podría escribirse como:

Path index = Paths.get("/home/Work/Indexer1");

if (!Files.exists(index)) {
    index = Files.createDirectories(index);
} else {

    Files.walk(index)
         .sorted(Comparator.reverseOrder())  // as the file tree is traversed depth-first and that deleted dirs have to be empty  
         .forEach(t -> {
             try {
                 Files.delete(t);
             } catch (IOException e) {
                 // LOG the exception and potentially stop the processing

             }
         });
    if (!Files.exists(index)) {
        index = Files.createDirectories(index);
    }
}
davidxxx
fuente
0

puedes intentar lo siguiente

  File dir = new File("path");
   if (dir.isDirectory())
   {
         dir.delete();
   }

Si hay subcarpetas dentro de su carpeta, es posible que deba eliminarlas de forma recursiva.

Ruchira Gayan Ranaweera
fuente
0
private void deleteFileOrFolder(File file){
    try {
        for (File f : file.listFiles()) {
            f.delete();
            deleteFileOrFolder(f);
        }
    } catch (Exception e) {
        e.printStackTrace(System.err);
    }
}
Marcelo Lopes
fuente
0
        import org.apache.commons.io.FileUtils;

        List<String> directory =  new ArrayList(); 
        directory.add("test-output"); 
        directory.add("Reports/executions"); 
        directory.add("Reports/index.html"); 
        directory.add("Reports/report.properties"); 
        for(int count = 0 ; count < directory.size() ; count ++)
        {
        String destination = directory.get(count);
        deleteDirectory(destination);
        }





      public void deleteDirectory(String path) {

        File file  = new File(path);
        if(file.isDirectory()){
             System.out.println("Deleting Directory :" + path);
            try {
                FileUtils.deleteDirectory(new File(path)); //deletes the whole folder
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        else {
        System.out.println("Deleting File :" + path);
            //it is a simple file. Proceed for deletion
            file.delete();
        }

    }

Funciona de maravilla . Tanto para carpetas como para archivos. Salam :)

Mushtaque Ahmed
fuente
-1

Eliminarlo de otra parte

File index = new File("/home/Work/Indexer1");
if (!index.exists())
{
     index.mkdir();
     System.out.println("Dir Not present. Creating new one!");
}
index.delete();
System.out.println("File deleted successfully");
Aniket Thakur
fuente
-1

Algunas de estas respuestas parecen innecesariamente largas:

if (directory.exists()) {
    for (File file : directory.listFiles()) {
        file.delete();
    }
    directory.delete();
}

También funciona para subdirectorios.

Adam corto
fuente
-3

Puedes usar esta función

public void delete()    
{   
    File f = new File("E://implementation1/");
    File[] files = f.listFiles();
    for (File file : files) {
        file.delete();
    }
}
Piyush Rumao
fuente
Funciona bien con un directorio con todos los archivos cerrados. Pero cuando se prueba en un directorio con archivos abiertos, no funciona. ¿Pueden ayudarme a encontrar una manera de eliminar la carpeta a pesar de los archivos abiertos?
Piyush Rumao
2
Esto no eliminará los subdirectorios que no estén vacíos.
Pang