Script de shell para eliminar directorios anteriores a n días

165

Tengo directorios nombrados como:

2012-12-12
2012-10-12
2012-08-08

¿Cómo eliminaría los directorios que tienen más de 10 días con un script de shell bash?

bobsr
fuente
1
¿Al descubierto alguna relación en su tiempo real de creación / modificación? Porque findpodría hacerlo sin mirar el nombre entonces ...
Wrikken
también deberían tener tiempo de creación / modificación
bobsr
44
¿Qué quieres decir con "mayor que"? ¿Se refiere a la hora en que se creó el directorio, la hora en que se modificó por última vez su contenido o algo más? Tenga cuidado con algunas de las respuestas a continuación; ctimees el tiempo de cambio de inodo. Para un directorio, cambia cuando se agregan o eliminan archivos del directorio.
ajk

Respuestas:

390

Esto lo hará recursivamente para ti:

find /path/to/base/dir/* -type d -ctime +10 -exec rm -rf {} \;

Explicación:

  • find: el comando unix para encontrar archivos / directorios / enlaces, etc.
  • /path/to/base/dir: el directorio para comenzar su búsqueda.
  • -type d: solo encuentra directorios
  • -ctime +10: solo considere los que tienen un tiempo de modificación mayor a 10 días
  • -exec ... \;: para cada resultado encontrado, realice el siguiente comando en ...
  • rm -rf {}: fuerza recursivamente eliminar el directorio; la {}parte es donde se sustituye el resultado de la búsqueda de la parte anterior.

Alternativamente, use:

find /path/to/base/dir/* -type d -ctime +10 | xargs rm -rf

Lo cual es un poco más eficiente, porque equivale a:

rm -rf dir1 dir2 dir3 ...

Opuesto a:

rm -rf dir1; rm -rf dir2; rm -rf dir3; ...

como en el -execmétodo


Con las versiones modernas de find, puede reemplazar ;con +y hará el equivalente de la xargsllamada por usted, pasando tantos archivos como quepan en cada llamada del sistema ejecutivo:

find . -type d -ctime +10 -exec rm -rf {} +
sampson-chen
fuente
12
-mtimefue mejor para mí, ya que comprueba los cambios de contenido en lugar de los cambios de permisos, de lo contrario, esto fue perfecto.
quickshiftin el
77
Creo que esto también eliminará el directorio base en sí
o Gal
3
@OrGal tienes toda la razón. Con el fin de evitar esto, sólo tiene que utilizar: find /path/to/base/dir/*.
zloynemec
11
puede usar -maxdepth 1 para ignorar el contenido de los directorios
Sam
77
El enfoque más eficiente puede ser contraproducente si tiene demasiadas carpetas para eliminar: stackoverflow.com/questions/11289551/… . Por la misma razón, para evitar la eliminación de la carpeta base es mejor usar -mindepth 1(en lugar de /path/to/folder/*).
Ohad Schneider
41

Si desea eliminar todos los subdirectorios en /path/to/base, por ejemplo

/path/to/base/dir1
/path/to/base/dir2
/path/to/base/dir3

pero no desea eliminar la raíz /path/to/base, debe agregar -mindepth 1y -maxdepth 1opciones, que accederán solo a los subdirectorios en/path/to/base

-mindepth 1excluye la raíz /path/to/basede las coincidencias.

-maxdepth 1se SOLAMENTE coincidir con los subdirectorios de inmediato bajo /path/to/basetales como /path/to/base/dir1, /path/to/base/dir2y /path/to/base/dir3sin embargo no lo hará Lista subdirectorios de éstos de manera recursiva. Por lo tanto, estos subdirectorios de ejemplo no se enumerarán:

/path/to/base/dir1/dir1
/path/to/base/dir2/dir1
/path/to/base/dir3/dir1

Etcétera.

Por lo tanto, para eliminar todos los subdirectorios en los /path/to/baseque tienen más de 10 días;

find /path/to/base -mindepth 1 -maxdepth 1 -type d -ctime +10 | xargs rm -rf
pmgarvey
fuente
19

findadmite -deleteoperación, entonces:

find /base/dir/* -ctime +10 -delete;

Creo que hay una trampa de que los archivos también deben tener más de 10 días de antigüedad. No lo he intentado, alguien puede confirmar en los comentarios.

Falta la solución más votada, -maxdepth 0por lo que llamará rm -rfa cada subdirectorio, después de eliminarlo. Eso no tiene sentido, así que sugiero:

find /base/dir/* -maxdepth 0  -type d -ctime +10 -exec rm -rf {} \;

La -deletesolución anterior no se usa -maxdepth 0porque findse quejaría de que el directorio no está vacío. En cambio, implica -depthy elimina de abajo hacia arriba.

Ondra Žižka
fuente
Puedo confirmar que -deletefunciona, pero como dijiste, solo puedes usarlo para eliminar directorios vacíos, al igual que rmdir.
CTodea
3

Estaba luchando por hacer esto bien usando los scripts proporcionados anteriormente y algunos otros scripts, especialmente cuando los archivos y los nombres de carpetas tenían nueva línea o espacios.

Finalmente tropecé con tmpreaper y hasta ahora nos ha funcionado bastante bien.

tmpreaper -t 5d ~/Downloads


tmpreaper  --protect '*.c' -t 5h ~/my_prg

Enlace fuente original

Tiene características como prueba, que comprueba los directorios de forma recursiva y los enumera. Posibilidad de eliminar enlaces simbólicos, archivos o directorios y también el modo de protección para un determinado patrón al eliminar

usuario_v
fuente
2

O

rm -rf `find /path/to/base/dir/* -type d -mtime +10`

Versión actualizada y más rápida de la misma:

find /path/to/base/dir/* -mtime +10 -print0 | xargs -0 rm -f
Increíble
fuente
2
Este podría exceder fácilmente la longitud máxima de la línea de comandos. Ver xargs --show-limits.
Michael Krupp
2
Tampoco funcionará si hay nombres de archivo que contienen espacios u otros caracteres especiales de shell.
Martin Tournoij
@Carpetsmoker ¿El -print0/ no -0se encarga de los caracteres especiales del shell, o no?
mpen
Tienes razón en que la xargsversión será @mpen, pero la primera línea no.
Martin Tournoij