Script para borrar contenido directorio pero NO el directorio
Buenas,
Resulta que hace un tiempo junto con unos amigos contraté un servidor Kimsufi de 100/100Mbps al que le instalamos un Debian GNU/Linux 5.0.4 (lenny).
El tema está en que llevo ya tiempo intentando crear un script que de alguna forma "Automantenga" el servidor limpio, para que no se llene el espacio del mismo (230GB... aprox). Así que con mis mínimos conocimientos de Linux y mirando mucho scripting he conseguido hacer el siguiente script:
# ---------- VARIABLES ----------
#
TEMPORAL="/home/temporal/temporal-utorrent /home/temporal/temporal-amule"
#
PATHFILE="/home/descargas/descargas /home/descargas/DVD /home/descargas/HD /home/descargas/Invitado/Games /home/descargas/Invitado/Musica /home/descargas/Invitado/Pelis /home/descargas/Invitado/Series /home/descargas/Juegos/PC /home/descargas/Juegos/Xbox360 /home/descargas/Juegos/Wii /home/descargas/Musica /home/descargas/Otros /home/descargas/Peliculas /home/descargas/Pelis_de_Culto /home/descargas/Series"
#
LOGFILE="/home/script/log.txt"
#
DATEDASHES="================================================================================="
#
FILEDASHES="---------------------------------------------------------------------------------"
#
# ---------- FUNCTIONS ---------
#
function deletedate {
echo $DATEDASHES >> $LOGFILE
echo "$0 started running at `date`" >> $LOGFILE
echo $DATEDASHES >> $LOGFILE
}
#
function deletedfiles {
echo $FILEDASHES >> $LOGFILE
echo "DELETED FILES" >> $LOGFILE
echo $FILEDASHES >> $LOGFILE
}
#
function deletedtemporals {
echo $FILEDASHES >> $LOGFILE
echo "DELETED TEMPORALS" >> $LOGFILE
echo $FILEDASHES >> $LOGFILE
}
#
# ---------- SCRIPTING ----------
#
deletedate
deletedfiles
find $PATHFILE -name "*" -mtime +10 -exec rm -rf '{}' \;
deletedtemporals
find $TEMPORAL -name "*" -mtime +30 >> $LOGFILE;
La idea fundamental de lo anterior es buscar el contenido de los directorios definidos en la variable "PATHFILE" y "TEMPORAL" y borrarlo cuando dicho contenido lleve sin modificarse un tiempo de:
- 10 Días para los contenidos definidos en la variable PATHFILE
- 30 Días para los contenidos definidos en la variable TEMPORAL
Asimismo, generar un log por cada vez que se ejecute el script que guarde precisamente la fecha de cuando se ha ejecutado dicho script y qué es lo que ha borrado.
Todo ello se ejecutará diariamente desde el crontab.
Mis [b][u]problemas[/u][/b] son los siguientes:
1. Quiero [b]borrar[/b] todo [b]el contenido del directorio[/b] que cumpla la condición anterior, [b]tanto archivos como directorios, pero no el directorio como tal[/b], sin embargo con el siguiente código, también me borra el directorio en el que estoy buscando:
find $PATHFILE -name "*" -mtime +10 -exec rm -rf '{}' \;
2. Quiero [b]mandar el log de lo borrado a la variable $LOGFILE[/b], sin embargo si escribo el siguiente código me aparece un mensaje diciéndome que el código "-exec le falta argumentos":
find $PATHFILE -name "*" -mtime +10 -exec rm -rf '{}' >> $LOGFILE;
De la siguiente forma, sí puedo mantener un log de lo que estoy buscando:
find $TEMPORAL -name "*" -mtime +30 >> $LOGFILE;
Pero en el momento que meto el -exec se fastidia la instrucción.
Me gustaría saber si lo anteriormente comentado es posible y si estoy cometiendo algún tipo de error de sintaxis... Agradecería cualquier tipo de ayuda.
Saludos y Gracias de Antemano!
- Inicie sesión o regístrese para enviar comentarios
- 1215 lecturas


Bienvenido a la comunidad y gracias por el aporte, has empezado con buen pie.
Saludos
Con etiquetas code tu post sería mucho más legible.
1. Quiero [b]borrar[/b] todo [b]el contenido del directorio[/b] que cumpla la condición anterior, [b]tanto archivos como directorios, pero no el directorio como tal[/b], sin embargo con el siguiente código, también me borra el directorio en el que estoy buscando:
find $PATHFILE -name "*" -mtime +10 -exec rm -rf '{}' \;
2. Quiero [b]mandar el log de lo borrado a la variable $LOGFILE[/b], sin embargo si escribo el siguiente código me aparece un mensaje diciéndome que el código "-exec le falta argumentos":
find $PATHFILE -name "*" -mtime +10 -exec rm -rf '{}' >> $LOGFILE;
De la siguiente forma, sí puedo mantener un log de lo que estoy buscando:
find $TEMPORAL -name "*" -mtime +30 >> $LOGFILE;
Pero en el momento que meto el -exec se fastidia la instrucción.
Me gustaría saber si lo anteriormente comentado es posible y si estoy cometiendo algún tipo de error de sintaxis... Agradecería cualquier tipo de ayuda.
Saludos y Gracias de Antemano!
En el apartado 1 haces un "find $PATHFILE" desde donde estés, así que lógicamente te borra ese path.
Mejor haz esto:
Primero "cd $PATHFILE"
y luego haces un "find . -name... etcétera"
Te dará el error de que no puede borrar el ".", pero como no podrá no hay problema ;-)
Error de sintaxis en el apartado 2:
te falta terminar con \; (ponlo igual que hiciste en el apartado 1)
Las comillas que pusiste a las llaves no son necesarias.
P.D.: Bienvenido a esDebian
Con etiquetas code tu post sería mucho más legible.
No me deja editar el post pasadas 3 horas, no puedo hacer nada para cambiarlo... siento las molestias.
1. Quiero [b]borrar[/b] todo [b]el contenido del directorio[/b] que cumpla la condición anterior, [b]tanto archivos como directorios, pero no el directorio como tal[/b], sin embargo con el siguiente código, también me borra el directorio en el que estoy buscando:
find $PATHFILE -name "*" -mtime +10 -exec rm -rf {} \;En el apartado 1 haces un "find $PATHFILE" desde donde estés, así que lógicamente te borra ese path.
Mejor haz esto:
Primero "cd $PATHFILE"
y luego haces un "find . -name... etcétera"
Te dará el error de que no puede borrar el ".", pero como no podrá no hay problema ;-)
He probado lo que me has comentado y funciona, no entiendo muy bien porqué, pero no borra el "." (osea el directorio en el que te encuentras). Sin embargo, surge un problemilla y es que el Pathfile está compuesto de varios paths:
PATHFILE="/home/descargas/descargas /home/descargas/DVD /home/descargas/HD /home/descargas/Invitado/Games /home/descargas/Invitado/Musica /home/descargas/Invitado/Pelis /home/descargas/Invitado/Series /home/descargas/Juegos/PC /home/descargas/Juegos/Xbox360 /home/descargas/Juegos/Wii /home/descargas/Musica /home/descargas/Otros /home/descargas/Peliculas /home/descargas/Pelis_de_Culto /home/descargas/Series"
Si hago "cd $PATHFILE", y después el "find . -name...", tan sólo me encuentra contenidos del primer path de todos los anteriores (/home/descargas/descargas). Si bien es cierto ésta podría ser una posible solución ya que podría hacer varios "cd PATH; find . -name...;" por cada uno de los PATHS en los que haya que buscar, pero quedaría un código muy repetitivo. Obviamente si no hay otra forma es tal y como lo haré, pero si la hay estaría bien saberla a fin de tener un script con un código más práctico.
2. Quiero [b]mandar el log de lo borrado a la variable $LOGFILE[/b], sin embargo si escribo el siguiente código me aparece un mensaje diciéndome que al código "-exec le faltan argumentos":
find $PATHFILE -name "*" -mtime +10 -exec rm -rf {} >> $LOGFILE;Con lo siguiente sí puedo mantener un log de lo que estoy buscando:
find $TEMPORAL -name "*" -mtime +30 >> $LOGFILE;Error de sintaxis en el apartado 2:
te falta terminar con \; (ponlo igual que hiciste en el apartado 1)
No me ha quedado del todo claro dónde tengo que terminar esa instrucción. He realizado las siguientes pruebas:
find $PATHFILE -name "*" -mtime +10 -exec rm -rf {} \; >> $LOGFILE;find $PATHFILE -name "*" -mtime +10 -exec rm -rf {} >> $LOGFILE \;
find $PATHFILE -name "*" -mtime +10 >> $LOGFILE -exec rm -rf {} \;
Haciendo cualquiera de ambas, borra correctamente lo que haya en dicho directorio, pero en ninguno de los dos casos me saca la salida en el log. De hecho me escribe en consola:
find: A<<./blabla>>: No existe el fichero o directorio
Así que entiendo que cuando va a realizar el log, vuelve a hacer el find y no encuentra nada ya que está borrado. He realizado el siguiente código que no sé como no se me ha ocurrido antes, utilizo una sentencia para guardar el log y otra para ejecutar la instrucción de borrado. Esto ha funcionado correctamente, el problema está en que te guarda en el log lo que ha encontrado (que posteriormente vas a borrar) pero no te guarda lo que ha borrado y eso era lo que quería exactamente..., pero bueno más o menos me puede servir.
find $PATHFILE -name "*" -mtime +10 >> $LOGFILE;find $PATHFILE -name "*" -mtime +10 -exec rm -rf {} \;
Saludos y Gracias!
@sazu85
Podrías guardar los paths en un archivo plano y luego recorrerlo en un ciclo for.
He probado lo que me has comentado y funciona, no entiendo muy bien porqué, pero no borra el "." (osea el directorio en el que te encuentras).
El por qué, lo respondes tú mismo: Porque es del directorio donde te encuentras y por lo tanto ese fichero (directorio en este caso) está ocupado por tu proceso, con lo cual no se puede borrar.
Sin embargo, surge un problemilla y es que el Pathfile está compuesto de varios paths:
PATHFILE="/home/descargas/descargas /home/descargas/DVD /home/descargas/HD /home/descargas/Invitado/Games /home/descargas/Invitado/Musica /home/descargas/Invitado/Pelis /home/descargas/Invitado/Series /home/descargas/Juegos/PC /home/descargas/Juegos/Xbox360 /home/descargas/Juegos/Wii /home/descargas/Musica /home/descargas/Otros /home/descargas/Peliculas /home/descargas/Pelis_de_Culto /home/descargas/Series"
Para recorrer la lista de $PATHFILE puedes hacer lo que te dice ratakruel o hacer esto:
set `echo $PATHFILE`Esto te meterá esa lista separada por blancos en variables $1, $2, $3... $n
Luego recorres esa lista con un bucle for (el comando shift te desplazará toda la lista hacia la izquierda y $3 pasará a ser $2, $2 será $1 y así)
No me ha quedado del todo claro dónde tengo que terminar esa instrucción.
{} \;Siempre que utilizas el parámetro "-exec" en el comando find lo tienes que terminar de esa forma. No me preguntes por qué, pero es así:
find $PATHFILE -name "*" -mtime +10 -exec rm -rf {} \; >> $LOGFILE;Por cierto, no sería necesario especificar
-name "*"ya que no estás restringiendo nada; le dices que coja cualquier fichero independientemente de su nombre.
Así que entiendo que cuando va a realizar el log, vuelve a hacer el find y no encuentra nada ya que está borrado. He realizado el siguiente código que no sé como no se me ha ocurrido antes, utilizo una sentencia para guardar el log y otra para ejecutar la instrucción de borrado. Esto ha funcionado correctamente, el problema está en que te guarda en el log lo que ha encontrado (que posteriormente vas a borrar) pero no te guarda lo que ha borrado y eso era lo que quería exactamente..., pero bueno más o menos me puede servir.
find $PATHFILE -name "*" -mtime +10 >> $LOGFILE;find $PATHFILE -name "*" -mtime +10 -exec rm -rf {} \;
Efectivamente, así es.
Saludos y Gracias!
Fue un placer.
Ah, se me ocurre otra cosa más sencilla:
Hacer el find de lo que hay, borrar todo sin piedad y después crear nuevamente los directorios.
Buenas y gracias por responder,
Junto con lo que me habéis comentado y investigando un poco, he encontrado 4 opciones para lo que quiero hacer, (seguro que hay más), pero creo que cualquiera de estas me sirve:
Hago lo que me has comentado Migu, hago que cada path dentro de la variable PATHFILES se convierta en una variable y posteriormente hago un for que recorra las variables, es decir, los paths y por cada uno de ellos que busque, lo guarde en el log y posteriormente borre todo lo que hay dentro.
set `echo $PATHFILE`cd $PATHFILE
for (i=0; i<$#; i++) {
cd $i
find . -mtime +10 >> $LOGFILE;
find . -mtime +10 -print0 | xargs -0 rm -rf;
}
Lo mismo que la anterior, el for tendría la función de recorrer todos los paths y buscar lo que hay dentro en base a una condición y de llamar a otro ejecutable que se encargaría de logear lo encontrado y de borrarlo.
cd $PATHFILEfor (i=0; i<$#; i++) {
cd $i
find . -mtime +10 -print0 | xargs -0 ./Borrar.sh;
}
<strong>Borrar.sh</strong>
#!/bin/bash
LOGFILE="/home/script/log.txt"
echo $1 >> $LOGFILE;
rm -rf $1;
Excluír los nombres de los directorios que no quiero borrar en la busqueda, guardarlo en el log y posteriormente borrarlo. El ! -name lo que hace es excluir los archivos con ese nombre, en ningún caso excluye lo que hay dentro del directorio, no sé si me he explicado. Lo he sacado de aquí.
find $PATHFILE ! -name "descargas" ! -name "DVD" ! -name "HD" ! -name "Invitado" ! -name "Games" ! -name "Musica" ! -name "Otros" ! -name "Peliculas" ! -name "Pelis_de_Culto" ! -name "Series" -mtime +10 >> $LOGFILE;find $PATHFILE ! -name "descargas" ! -name "DVD" ! -name "HD" ! -name "Invitado" ! -name "Games" ! -name "Musica" ! -name "Otros" ! -name "Peliculas" ! -name "Pelis_de_Culto" ! -name "Series" -mtime +10 -print0 | xargs -0 rm -rf;
El mismo proceso que en el caso anterior, pero en vez de hacer dos finds, hago un find que busque lo que quiero y posteriormente que llame a la función que crea el log y borra.
find $PATHFILE ! -name "descargas" ! -name "DVD" ! -name "HD" ! -name "Invitado" ! -name "Games" ! -name "Musica" ! -name "Otros" ! -name "Peliculas" ! -name "Pelis_de_Culto" ! -name "Series" -mtime +10 -print0 | xargs -0 ./Borrar.sh;<strong>Borrar.sh</strong>
#!/bin/bash
LOGFILE="/home/script/log.txt"
echo $1 >> $LOGFILE;
rm -rf $1;
Agradecería que me miraséis la sintaxis por si no está del todo correcta! Creo que está todo más o menos bien, pero seguro que alguna cosilla anda mal... Esta noche cuando llegue del trabajo lo probaré todo.
De todas formas, tengo una duda, podéis ver que en la opción B y D llamo a otro ejecutable, podría ser esto una función en vez de otro script y llamarla desde el propio -exec o desde el xargs?
Saludos y Muchas gracias por todo!
Buenas,
Finalmente me he decantado por la opción C, después de haber estado haciendo pruebas y comprobando rendimientos del tiempo requerido para la realización del script con la clausula time delante del find.
Os dejo el código completo por si le pudiera servir a alguien:
#!/bin/bash# Script Name: Autoclean.sh
# Author Name: Jago
# Date: Sat March 10 1:08:32 JST 2010
# Description: This script will do the following:
# 1. Clean up the following directories where its files havent been modified in the last 10 days:
# - Descargas
# - DVD
# - Games (PC | Wii | Xbox360)
# - HD
# - Invitado (Games | Musica | Peliculas | Series)
# - Musica
# - Otros
# - Peliculas
# - Pelis de Culto
# - Series
# 2. Clean un the following directories where its files haven been modified in the last 50 days:
# - Temporal de Utorrent
# - Temporal de Amule
# 3. Create a log with the deleted files from the directories above.
#
#
# ---------- VARIABLES ----------
#
TEMPORAL="/home/temporal/temporal-utorrent /home/temporal/temporal-amule"
#
PATHFILE="/home/descargas/descargas /home/descargas/DVD /home/descargas/Games /home/descargas/HD /home/descargas/Invitado /home/descargas/Musica /home/descargas/Otros /home/descargas/Peliculas /home/descargas/Pelis_de_Culto /home/descargas/Series"
#
LOGFILE="/home/script/Borrado.log"
#
DATEDASHES="================================================================================="
#
FILEDASHES="---------------------------------------------------------------------------------"
#
# ---------- FUNCTIONS ---------
#
function deletedate {
echo $DATEDASHES >> $LOGFILE
echo "$0 started running at `date`" >> $LOGFILE
echo $DATEDASHES >> $LOGFILE
}
#
function deletedfiles {
echo $FILEDASHES >> $LOGFILE
echo "DELETED FILES" >> $LOGFILE
echo $FILEDASHES >> $LOGFILE
}
#
function deletedtemporals {
echo $FILEDASHES >> $LOGFILE
echo "DELETED TEMPORALS" >> $LOGFILE
echo $FILEDASHES >> $LOGFILE
}
#
# ---------- SCRIPTING ----------
#
deletedate
deletedfiles
find $PATHFILE ! -name "descargas" ! -name "DVD" ! -name "Games" ! -name "HD" ! -name "Invitado" ! -name "Musica" ! -name "Otros" ! -name "Peliculas" ! -name "Pelis_de_Culto" ! -name "Series" ! -name "PC" ! -name "Wii" ! -name "Xbox360" -mtime +15 >> $LOGFILE;
find $PATHFILE ! -name "descargas" ! -name "DVD" ! -name "Games" ! -name "HD" ! -name "Invitado" ! -name "Musica" ! -name "Otros" ! -name "Peliculas" ! -name "Pelis_de_Culto" ! -name "Series" ! -name "PC" ! -name "Wii" ! -name "Xbox360" -mtime +15 -print0 | xargs -0 rm -rf;
deletedtemporals
find $TEMPORAL ! -name "temporal-amule" ! -name "temporal-utorrent" -mtime +30 >> $LOGFILE;
find $TEMPORAL ! -name "temporal-amule" ! -name "temporal-utorrent" -mtime +30 -print0 | xargs -0 rm -rf;
Saludos y Gracias por todo!