2012-07-23 13 views
5

che avevo usato in precedenza un semplice comando find per eliminare tar non file utilizzati negli ultimi x giorni (in questo esempio, 3 giorni):script Bash per limitare una dimensione directory eliminando i file a cui si accede ultima

find /PATH/TO/FILES -type f -name "*.tar" -atime +3 -exec rm {} \; 

Ora ho bisogno di migliorare questo script eliminando in ordine di data di accesso e le mie abilità di scrittura bash sono un po 'arrugginite. Ecco cosa ho bisogno di fare:

  1. controllo la dimensione di una directory/path/to/FILE
  2. se la dimensione in 1) è maggiore di dimensioni X, ottenere un elenco dei file in base alla data di accesso
  3. cancellare i file in ordine fino a quando la dimensione è inferiore a X

il vantaggio è per la cache e di backup delle directory, io eliminerà solo le cose che ho bisogno di mantenerlo entro un limite, mentre il metodo semplificato potrebbe andare oltre limite di dimensioni se un giorno è particolarmente grande. Sto indovinando che ho bisogno di usare stat e una bash per il ciclo?

risposta

4

Ecco un semplice, facile da leggere e capire il metodo che mi è venuta per fare questo:

DIRSIZE=$(du -s /PATH/TO/FILES | awk '{print $1}') 
if [ "$DIRSIZE" -gt "$SOMELIMIT" ] 
    then 
    for f in `ls -rt --time=atime /PATH/TO/FILES/*.tar`; do 
    FILESIZE=`stat -c "%s" $f` 
    FILESIZE=$(($FILESIZE/1024)) 

    DIRSIZE=$(($DIRSIZE - $FILESIZE)) 
    if [ "$DIRSIZE" -lt "$LIMITSIZE" ]; then 
     break 
    fi 
done 
fi 
+1

Penso che questo script sia un buon inizio, ma in realtà non risponde alla domanda. Hai chiesto come eliminare i file in modo che la dimensione della directory rientri sotto la soglia. La tua risposta qui non sembra cancellare nulla, semplicemente ordina i file e li scorre attraverso di essi. Sembra che ti manchi un "rm" qui da qualche parte. –

1

Non ho bisogno di usare i loop, solo qualche applicazione accurata di stat e awk. Dettagli e spiegazioni di seguito, prima del codice:

find /PATH/TO/FILES -name '*.tar' -type f \ 
| sed 's/ /\\ /g' \ 
| xargs stat -f "%a::%z::%N" \ 
| sort -r \ 
| awk ' 
    BEGIN{curSize=0; FS="::"} 
    {curSize += $2} 
    curSize > $X_SIZE{print $3} 
    ' 
| sed 's/ /\\ /g' \ 
| xargs rm 

Si noti che questa è una linea di ordine logico, ma per il bene della sanità mentale ho diviso in su.

Inizia con un comando di ricerca basato su quello precedente, senza le parti che lo limitano a file precedenti a 3 giorni. Conduce a sed, per evitare qualsiasi spazio nei nomi dei file, trova i ritorni, quindi usa xargs per eseguire statistiche su tutti i risultati. Il -f "% a ::% z ::% N" indica stat al formato da utilizzare, con l'ora dell'ultimo accesso nel primo campo, la dimensione del file nel secondo e il nome del file nel terzo. Ho usato '::' per separare i campi perché è più facile gestire gli spazi nei nomi dei file in questo modo. Ordina quindi li ordina sul primo campo, con -r per invertire l'ordine.

Ora abbiamo un elenco di tutti i file che ci interessano, in ordine dall'ultimo accesso al più recente accesso. Quindi lo script awk somma tutte le dimensioni mentre passa attraverso l'elenco e inizia a emetterle quando supera $ X_SIZE. I file che non vengono stampati in questo modo saranno quelli mantenuti, gli altri nomi di file torneranno a sed di nuovo per sfuggire a qualsiasi spazio e quindi a xargs, che li esegue.

+0

Questa soluzione non ha funzionato. Ho migliorato la sceneggiatura e pubblicato il risultato come una risposta separata. –

+0

L'idea è stata fantastica. Grazie. –

6

ho migliorato l'esempio di brunner314 e risolto i problemi al suo interno.

Ecco uno script di lavoro che sto utilizzando:

#!/bin/bash 
DELETEDIR="$1" 
MAXSIZE="$2" 
if [[ -z "$DELETEDIR" || -z "$MAXSIZE" || "$MAXSIZE" -lt 1 ]]; then 
    echo "usage: $0 [directory] [maxsize in megabytes]" >&2 
    exit 1 
fi 
find "$DELETEDIR" -type f -printf "%[email protected]::%p::%s\n" \ 
| sort -rn \ 
| awk -v maxbytes="$((1024 * 1024 * $MAXSIZE))" -F "::" ' 
    BEGIN { curSize=0; } 
    { 
    curSize += $3; 
    if (curSize > maxbytes) { print $2; } 
    } 
    ' \ 
    | tac | awk '{printf "%s\0",$0}' | xargs -0 -r rm 
# delete empty directories 
find "$DELETEDIR" -mindepth 1 -depth -type d -empty -exec rmdir "{}" \; 
Problemi correlati