Diciamo che ho una directory ḟoo/
che contiene molti file in una sorta di struttura di directory. Devo tenerne alcuni, ma non tutti.
C'è un modo per (sul posto) eliminarli tutti tranne (diciamo) 500 più recenti?
Diciamo che ho una directory ḟoo/
che contiene molti file in una sorta di struttura di directory. Devo tenerne alcuni, ma non tutti.
C'è un modo per (sul posto) eliminarli tutti tranne (diciamo) 500 più recenti?
Risposte:
Faccio questo compito regolarmente e utilizzo varianti del seguente. È una pipeline che combina vari semplici strumenti: trova tutti i file, anteponi il tempo di modifica del file, ordina, rimuovi il tempo di modifica del file, visualizza prima tutte le righe tranne la 500 e rimuovile:
find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
sort -r | cut -c14- | tail -n +501 | \
while read file; do rm -f -- "$file"; done
Alcuni commenti:
Se stai usando "bash", dovresti usare "read -r file", non solo "read file".
L'uso di "perl" per rimuovere i file è più veloce (e gestisce anche i caratteri "strani" nei nomi dei file meglio del ciclo while, a meno che non si stia utilizzando "read -r file"):
... | tail -n +501 | perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
Alcune versioni di "tail" non supportano l'opzione "-n", quindi è necessario utilizzare "tail +501". Un modo portatile per saltare le prime 500 linee è
... | perl -wnle 'print if $. > 500' | ...
Non funzionerà se i nomi dei tuoi file contengono nuove righe.
Non richiede GNU find.
La combinazione di quanto sopra ti dà:
find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
sort -r | cut -c14- | perl -wnle 'print if $. > 500' | \
perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
È così che lo farei in Python 3. che dovrebbe funzionare anche con altri sistemi operativi. Dopo averlo verificato, assicurati di decommentare la riga che rimuove effettivamente i file.
import os,os.path
from collections import defaultdict
FILES_TO_KEEP = 500
ROOT_PATH = r'/tmp/'
tree = defaultdict(list)
# create a dictionary containing file names with their date as the key
for root, dirs, files in os.walk(ROOT_PATH):
for name in files:
fname = os.path.join(root,name)
fdate = os.path.getmtime( fname )
tree[fdate].append(fname)
# sort this dictionary by date
# locate where the newer files (that you want to keep) end
count = 0
inorder = sorted(tree.keys(),reverse=True)
for key in inorder:
count += len(tree[key])
if count >= FILES_TO_KEEP:
last_key = key
break
# now you know where the newer files end, older files begin within the dict
# act accordingly
for key in inorder:
if key < last_key:
for f in tree[key]:
print("remove ", f)
# uncomment this next line to actually remove files
#os.remove(f)
else:
for f in tree[key]:
print("keep ", f)
Non conosco il "500 più recente", ma con find puoi eliminare cose che sono vecchie di X minuti / giorni. Esempio per file e precedenti a 2 giorni:
find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \;
Prima prova con:
find foo/ -mtime +2 -a -type f -exec ls -al \{\} \;
Fai attenzione alle barre rovesciate e allo spazio prima di "\;". Vedi la pagina man di ricerca per maggiori informazioni.
perché non usare questo codice più semplice:
$ ls -t1 foo/| xargs -d '\n' rm --
rm -f
però.