2011-12-21 13 views
6

Tenga en cuenta que no puedo utilizar 'encontrar' en el entorno de destino¿Cómo puedo encontrar y eliminar archivos basados ​​en la fecha en un script de shell de Linux sin encontrarlo?

necesito para eliminar todos los archivos de más de 7 días de edad en una secuencia de comandos shell de Linux. Algo así como:

FILES=./path/to/dir 
for f in $FILES 
do 
    echo "Processing $f file..." 
    # take action on each file. $f store current file name 
    # perhaps stat each file to get the last modified date and then delete files with date older than today -7 days. 

done 

¿Puedo usar 'stat' para hacer esto? Yo estaba tratando de usar

find *.gz -mtime +7 -delete 

pero descubrí que no puedo usar encontrar en el sistema de destino (no hay permiso para el usuario cron y esto no se puede cambiar). El sistema objetivo es Redhat Enterprise.

Los nombres de los archivos tienen el formato siguiente manera:

gzip>/mnt/target03/resto-de-path/web/backups/DATABASENAME_ date "+%Y-%m-%d" .gz

Respuesta

3

continuación Puesto que usted tiene el tiempo en el nombre del archivo que se utilice en cuando la eliminación heres un código que hace que:

Este script obtiene la hora actual en segundos desde el periodo y luego calcula la marca de tiempo hace 7 días. Luego, para cada archivo, se analiza el nombre del archivo y se convierte la fecha embebida en cada nombre de archivo en una marca de tiempo, luego se comparan las marcas de tiempo para determinar qué archivos eliminar. El uso de marcas de tiempo elimina todas las molestias al trabajar con fechas directamente (año bisiesto, diferentes días en meses, etc.)

La eliminación real está comentada para que pueda probar el código.

#funciton to get timestamp X days prior to input timestamp 
# arg1 = number of days past input timestamp 
# arg2 = timestamp (e.g. 1324505111) seconds past epoch 
getTimestampDaysInPast() { 
    daysinpast=$1 
    seconds=$2 
    while [ $daysinpast -gt 0 ] ; do 
    daysinpast=`expr $daysinpast - 1` 
    seconds=`expr $seconds - 86400` 
    done 
# make midnight 
    mod=`expr $seconds % 86400` 
    seconds=`expr $seconds - $mod` 
    echo $seconds 
} 
# get current time in seconds since epoch 
getCurrentTime() { 
    echo `date +"%s"` 
} 

# parse format and convert time to timestamp 
# e.g. 2011-12-23 -> 1324505111 
# arg1 = filename with date string in format %Y-%m-%d 
getFileTimestamp() { 
    filename=$1 
    date=`echo $filename | sed "s/[^0-9\-]*\([0-9\-]*\).*/\1/g"` 
    ts=`date -d $date | date +"%s"` 
    echo $ts 
} 

########################### MAIN ############################ 
# Expect directory where files are to be deleted to be first 
# arg on commandline. If not provided then use current working 
# directory 

FILEDIR=`pwd` 
if [ $# -gt 0 ] ; then 
    FILEDIR=$1 
fi 
cd $FILEDIR 

now=`getCurrentTime` 
mustBeBefore=`getTimestampDaysInPast 7 $now` 
SAVEIFS=$IFS 
# need this to loop around spaces with filenames 
IFS=$(echo -en "\n\b") 
# for safety change this glob to something more restrictive 
for f in * ; do 
    filetime=`getFileTimestamp $f` 
    echo "$filetime lt $mustBeBefore" 
    if [ $filetime -lt $mustBeBefore ] ; then 
    # uncomment this when you have tested this on your system 
    echo "rm -f $f" 
    fi 
done 
# only need this if you are going to be doing something else 
IFS=$SAVEIFS 
+0

Tengo intentado usar este código, pero acaba de obtener este resultado: 1325559634 1324944000 lt lt lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 1325559635 1324944000 lt lt lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 – codecowboy

+0

El eco "rm -f $ f" nunca parece funcionar. Los archivos se llaman así - eeSwap_2011-12-20.gz. ¿La expresión regular captará este nombre de archivo correctamente? – codecowboy

+0

Resulta que ts = 'date -d $ date | date + "% s" 'debe ser ts =' date -d "$ date" + "% s" 'El script funciona – codecowboy

8

esto debería funcionar:

#!/bin/sh 

DIR="/path/to/your/files" 
now=$(date +%s) 
DAYS=30 

for file in "$DIR/"* 
do 
    if [ $(((`stat $file -c '%Y'`) + (86400 * $DAYS))) -lt $now ] 
    then 
    # process/rm/whatever the file... 
    fi 
done 

Un poco de explicación: stat <file> -c '%Z' da la hora de modificación del archivo como segundos desde la época de UNIX para un archivo, y $(date +%s) da la marca de tiempo de UNIX actual. Luego, solo hay una simple comprobación para ver si la marca de tiempo del archivo, más siete días de segundos, es mayor que la marca de tiempo actual.

+0

Gracias - estoy recibiendo errores de una falta ')'. ¿Debe $ ahora también estar entre comillas? Estoy poniendo $ (rm "$ file") donde está tu comentario. – codecowboy

+0

Solo deberías poner 'rm" $ file "' – pgl

+0

@pgl Gracias por este impresionante script, pero no funcionó en busybox, necesitaba un masaje, así que así es como funcionó: '#!/ Bin/sh DIR = "/ ruta/a/su/archivos" ahora = $ (% s fecha +) DIAS = 30 de archivo en "$ DIR /" * hacer si [$ ((('stat $ archivo -c '% Y'') + (86400 * $ DAYS))) -lt $ ahora] luego # proceso/rm/cualquiera que sea el archivo ... fi done' – valentt

2

Si prefiere depender de la fecha en los nombres de archivo, puede utilizar esta rutina, que comprueba si una fecha es más antiguo que otro:

is_older(){ 
    local dtcmp=`date -d "$1" +%Y%m%d`; shift 
    local today=`date -d "$*" +%Y%m%d` 
    return `test $((today - dtcmp)) -gt 0` 
} 

y luego puede recorrer los nombres de archivo, pasando '- 7 días como la segunda fecha:

for filename in *; 
do 
    dt_file=`echo $filename | grep -o -E '[12][0-9]{3}(-[0-9]{2}){2}'` 
    if is_older "$dt_file" -7 days; then 
     # rm $filename or whatever 
    fi 
done 

en is_older rutina, date -d "-7 days" +%Y%m%d devolverá la fecha de 7 días antes, en formato numérico listo para la comparación.

0
DIR='' 

now=$(date +%s) 

for file in "$DIR/"* 
do 
echo $(($(stat "$file" -c '%Z') + $((86400 * 7)))) 
echo "----------" 
echo $now 

hecho

Cuestiones relacionadas