Eliminazione di tutto tranne i file più recenti


8

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:


11

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"'

Starei attento rm -fperò.
un CVn del

Funziona come un fascino! Questo dovrebbe essere disponibile come alias con $ path e $ count params. Molte grazie!
Dalibor Karlovic

4

È 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)

4

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.


Il "(diciamo) 500 più recente" è l'essenza qui, quindi non vedo come questo risponda alla domanda originale.
Peter John Acklam,

Scusa, non mi è stato chiaro.
AndreasM,

3

se potessi fare con il mantenimento dei file x giorni / ore anziché il numero x più recente, potresti farlo solo con tmpwatch --ctime 7d


2

Credo che l' -mtimee -neweropzioni di findcomando sono utili per voi. Puoi vedere man findper maggiori informazioni.


0

perché non usare questo codice più semplice:

$ ls -t1 foo/| xargs -d '\n' rm --

1
In che modo questo rimuove tutti i file tranne i 500 file più recenti? E come gestisce le sottodirectory? Penso che potresti aver frainteso il post originale.
Peter John Acklam,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.