¿Hay alguna forma de eliminar directorios enteros de forma recursiva en Java?
En el caso normal, es posible eliminar un directorio vacío. Sin embargo, cuando se trata de eliminar directorios completos con contenido, ya no es tan simple.
¿Cómo se eliminan directorios completos con contenido en Java?
java
file-io
filesystems
delete-directory
paweloque
fuente
fuente
Respuestas:
Deberías echar un vistazo a commons-io de Apache . Tiene una clase FileUtils que hará lo que quieras.
fuente
Con Java 7, finalmente podemos hacer esto con una detección confiable de enlaces simbólicos. (No considero que commons-io de Apache tenga una detección confiable de enlaces simbólicos en este momento, ya que no maneja enlaces en Windows creados con
mklink
).Por el bien de la historia, aquí hay una respuesta anterior a Java 7, que sigue a los enlaces simbólicos.
fuente
foo
con un enlace defoo/link
tal maneralink->/
, ¡las llamadasdelete(new File(foo))
eliminarán la mayor parte de su sistema de archivos como lo permita su usuario!En Java 7+ puedes usar
Files
class. El código es muy simple:fuente
super.postVisitDirectory(dir, exc);
a supostVisitDirectory
método, para hacer estallar si la caminata no pudo enumerar un directorio.Solución única (Java8) para eliminar todos los archivos y directorios de forma recursiva, incluido el directorio de inicio:
Usamos un comparador para el orden inverso, de lo contrario File :: delete no podrá eliminar el directorio posiblemente no vacío. Entonces, si desea mantener directorios y solo eliminar archivos, simplemente elimine el comparador en sorted () o elimine la clasificación por completo y agregue el filtro de archivos:
fuente
.sorted(Comparator.reverseOrder())
la sugerenciaComparator::reverseOrder
no no trabajar. Ver: stackoverflow.com/questions/43036611/….sorted((f1, f2) -> f2.compareTo(f1))
comparandof2
con enf1
lugar def1
conf2
.Java 7 agregó soporte para directorios móviles con manejo de enlaces simbólicos:
Lo uso como alternativa de los métodos específicos de la plataforma (en este código no probado ):
(SystemUtils es de Apache Commons Lang . Los procesos son privados pero su comportamiento debería ser obvio).
fuente
Acabo de ver que mi solución es más o menos la misma que la de Erickson, solo empaquetada como un método estático. Deje esto en algún lado, es mucho más liviano que instalar todos los Apache Commons para algo que (como puede ver) es bastante simple.
fuente
Una solución con una pila y sin métodos recursivos:
fuente
list*
métodos para la clasejava.io.File
. De los Javadocs: "Devuelve nulo si este nombre de ruta abstracto no denota un directorio, o si ocurre un error de E / S". Por lo tanto:if (currList.length > 0) {
se convierte enif (null != currList && currList.length > 0) {
Si tiene Spring, puede usar FileSystemUtils.deleteRecursively :
fuente
La guayaba había
Files.deleteRecursively(File)
apoyado hasta la guayaba 9 .De guayaba 10 :
Por lo tanto, no existe tal método en Guava 11 .
fuente
O si quieres manejar el
IOException
:fuente
Files.walk(path).iterator().toSeq.reverse.foreach(Files.delete)
walk
método ya garantiza un recorrido transversal en profundidad.Collections.reverseOrder()
lo que su código supondría quefor (Path p : Files.walk(directoryToDelete).sorted(reverseOrder()).toArray(Path[]::new))
se ha importado estáticamente.Comparator.reverseOrder
?Files.walk(dir) .sorted(Comparator.reverseOrder()) .toArray(Path[]::new))
fuente
fuente
f.delete()
debajodeleteDirectory(f)
arrojará NoSuchFileException porquedeleteDirectory(f)
ya elimina ese archivo. Cada directorio se convertirá en una ruta cuando sea pasadodeleteDirectory(f)
y eliminado porpath.delete()
. Por lo tanto, no necesitamosf.delete()
en laif f.isDerectory
sección. Entonces, simplemente eliminef.delete();
en deleteDirectory (f) y funcionará.Dos formas de fallar con los enlaces simbólicos y el código anterior ... y no conozco la solución.
Camino # 1
Ejecute esto para crear una prueba:
Aquí puede ver su archivo de prueba y el directorio de prueba:
Luego ejecute su commons-io deleteDirectory (). Se bloquea al decir que no se encuentra el archivo. No estoy seguro de lo que hacen los otros ejemplos aquí. El comando rm de Linux simplemente eliminaría el enlace, y rm -r en el directorio también lo haría.
Camino # 2
Ejecute esto para crear una prueba:
Aquí puede ver su archivo de prueba y el directorio de prueba:
Luego ejecute su commons-io deleteDirectory () o el código de ejemplo que publicaron las personas. No solo elimina el directorio, sino también el archivo de prueba que está fuera del directorio que se está eliminando. (Elimina la referencia del directorio implícitamente y elimina los contenidos). rm -r eliminaría solo el enlace. Debe usar algo como esto, elimine los archivos desreferenciados: "find -L dirtodelete -type f -exec rm {} \;".
fuente
Podrías usar:
org.apache.commons.io.FileUtils.deleteQuietly(destFile);
Elimina un archivo, nunca arroja una excepción. Si el archivo es un directorio, elimínelo y todos los subdirectorios. La diferencia entre File.delete () y este método es: Un directorio a eliminar no tiene que estar vacío. No se producen excepciones cuando un archivo o directorio no se puede eliminar.
fuente
Una solución óptima que maneja la excepción de manera consistente con el enfoque de que una excepción lanzada desde un método siempre debe describir lo que ese método estaba intentando (y no pudo) hacer:
fuente
En proyectos heredados, necesito crear código Java nativo. Creo este código similar al código Paulitex. Mira eso:
Y la prueba de la unidad:
fuente
El siguiente código borra recursivamente todo el contenido de una carpeta determinada.
fuente
Aquí hay un método principal básico que acepta un argumento de línea de comando, es posible que deba agregar su propia comprobación de errores o moldearlo como mejor le parezca.
¡Espero que eso ayude!
fuente
Quizás una solución para este problema podría ser volver a implementar el método de eliminación de la clase File usando el código de la respuesta de erickson:
fuente
Sin Commons IO y <Java SE 7
fuente
Si bien los archivos se pueden eliminar fácilmente usando file.delete (), los directorios deben estar vacíos para eliminarse. Use la recursividad para hacer esto fácilmente. Por ejemplo:
fuente
Codifiqué esta rutina que tiene 3 criterios de seguridad para un uso más seguro.
fuente
Bueno, supongamos un ejemplo,
Para obtener más información, consulte los siguientes recursos
Eliminar directorio
fuente
rm -rf
fue mucho más eficiente queFileUtils.deleteDirectory
.Después de una evaluación comparativa exhaustiva, descubrimos que usar
rm -rf
era varias veces más rápido que usarFileUtils.deleteDirectory
.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 con
FileUtils.deleteDirectory
y solo 1 minuto conrm -rf
.Aquí está nuestra implementación aproximada de Java para hacer eso:
Vale la pena intentarlo si se trata de directorios grandes o complejos.
fuente
La guayaba ofrece una línea:
MoreFiles.deleteRecursively()
.A diferencia de muchos de los ejemplos compartidos, tiene en cuenta los enlaces simbólicos y no (por defecto) eliminará los archivos fuera de la ruta proporcionada.
fuente