¿Cómo puedo eliminar todos los directorios vacíos en un subárbol? Usé algo como
find . -type d -exec rmdir {} 2>/dev/null \;
pero necesito que me ejecuten varias veces para eliminar directorios que solo contienen directorios vacíos. Además, es bastante lento, especialmente bajo cygwin.

Respuestas:
Combinando
findopciones y predicados de GNU , este comando debería hacer el trabajo:-type dse restringe a los directorios-emptyse restringe a los vacíos-deleteelimina cada directorioEl árbol se camina desde las hojas sin la necesidad de especificar,
-depthya que está implícito-delete.fuente
-deleteya implica,-depthpor lo que no necesita especificarlo manualmente.-mindepth 1aquí, para evitar eliminar el directorio de inicio en sí, si estuviera vacío.!tiene un significado especial para la concha. Necesitas escapar de eso. Algo así como:\! -name 'Completed'justo antes-deletedebería funcionar. O simplemente coloca un archivo marcador en este directorio.Enumere los directorios profundamente anidados primero.
(Tenga en cuenta que la redirección se aplica al
findcomando como un todo, no solo armdir. Redirigir solo pararmdircausaría una desaceleración significativa ya que necesitaría invocar un shell intermedio).Puede evitar ejecutarse
rmdiren directorios no vacíos pasando el-emptypredicado para buscar. GNU find prueba el directorio cuando está a punto de ejecutar el comando, por lo que se recogerán los directorios que se acaban de vaciar.Otra forma de acelerar sería agrupar las
rmdirinvocaciones. Es probable que ambos sean notablemente más rápidos que el original, especialmente bajo Cygwin. No espero mucha diferencia entre estos dos.El método más rápido depende de cuántos directorios no vacíos tenga. No puede combinarse
-emptycon métodos para agrupar invocaciones, porque los directorios que solo contienen directorios vacíos no están vacíos cuando losfindmira.Otro método sería ejecutar múltiples pases. Si esto es más rápido depende de muchas cosas, incluso si toda la jerarquía de directorios puede permanecer en el caché del disco entre
findejecuciones.Alternativamente, use zsh. El calificador glob
Fcoincide con directorios no vacíos, por lo que/^Fcoincide con directorios vacíos. Los directorios que solo contienen directorios vacíos no pueden coincidir tan fácilmente.(Esto termina cuando
rmdirrecibe una línea de comando vacía).fuente
-p? No hubiera pensado que haría la diferencia.-emptydebería funcionar con esta (aunque no estoy seguro exactamente cuánto ganará). Y muy, muy trivialmente, ya que probablemente no quieras eliminarlo., úsalo-mindepth 1.-depthargumento, que hacermdir -pinútil. Ya he cambiado mi comentario. Los años 90 fueron mi intento original; No hay nada sorprendente aquí.rmdirllamada de comando por completo, al menos con GNU find, con este comando:find . -depth -type d -empty -deleteSi solo agregas un
-pa turmdir, eso funcionará en una sola pasada. No será bonito u óptimo, pero debería tenerlo todo. Eso le dice a rmdir que elimine los directorios principales no vacíos del que está eliminando.Puede ahorrar un poco agregando la
-emptyprueba para buscar, para que no se moleste con directorios no vacíos.fuente
find . -depth -type d -exec rmdir {} +es la respuesta más simple y estándar a esta pregunta.
Desafortunadamente, las otras respuestas dadas aquí dependen de mejoras específicas del proveedor que no existen en todos los sistemas.
fuente
find . -type d -printf "%d %p\n" |\ sort -nr |\ perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ doneAsí es como funciona:
rmdiren la lista uno por unofuente
Utilizo estos alias para los
findcomandos de uso frecuente , especialmente cuando limpio el espacio en disco usando dupeguru , donde eliminar duplicados puede generar muchos directorios vacíos.Comentarios en el interior
.bashrcpara no olvidarlos más tarde cuando necesite modificarlo.fuente
rm -r */El comando funcionó fácilmente para mí.rmdebería requerir la-feliminación forzosa de directorios con archivos.rm -rsolo debe eliminar directorios vacíos. Estoy abierto a por qué esto podría estar mal. Esto también debería dejar archivos, ya que*/solo mira las carpetas.fuente
rmestá destinado principalmente a eliminar archivos. Si bien*/solo coincide con directorios, no tengo idea de lo que hace en niveles más profundos. También puedo imaginar que solo funciona en algunos sistemas.