Alles außer den neuesten Dateien löschen

8

Nehmen wir an, ich habe ein Verzeichnis, ḟoo/das viele Dateien in einer Art Verzeichnisstruktur enthält. Ich muss einige von ihnen behalten, aber nicht alle.

Gibt es eine Möglichkeit, alle zu löschen, außer (sagen wir) 500 neuesten?

Dalibor Karlović
quelle

Antworten:

11

Ich mache diese Aufgabe regelmäßig und verwende Varianten der folgenden. Es handelt sich um eine Pipeline, die verschiedene einfache Tools kombiniert: Suchen Sie alle Dateien, stellen Sie die Änderungszeit für Dateien voran, sortieren Sie, entfernen Sie die Änderungszeit für Dateien, zeigen Sie alle Zeilen mit Ausnahme der 500 zuerst an und entfernen Sie sie:

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

Ein paar Kommentare:

  • Wenn Sie "bash" verwenden, sollten Sie "read -r file" verwenden, nicht nur "read file".

  • Die Verwendung von "Perl" zum Entfernen der Dateien ist schneller (und behandelt auch "seltsame" Zeichen in den Dateinamen besser als die while-Schleife, es sei denn, Sie verwenden "read -r file"):

    ... | tail -n +501 | perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
    
  • Einige Versionen von "tail" unterstützen die Option "-n" nicht, daher müssen Sie "tail +501" verwenden. Eine tragbare Möglichkeit, die 500 ersten Zeilen zu überspringen, ist

     ... | perl -wnle 'print if $. > 500' | ...
    
  • Es funktioniert nicht, wenn Ihre Dateinamen Zeilenumbrüche enthalten.

  • Es ist keine GNU-Suche erforderlich.

Wenn Sie das oben Genannte kombinieren, erhalten Sie:

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"'
Peter John Acklam
quelle
Ich würde allerdings vorsichtig sein rm -f.
Ein CVn
Klappt wunderbar! Dies sollte als Alias ​​mit den Parametern $ path und $ count verfügbar sein. Vielen Dank!
Dalibor Karlović
4

So würde ich es in Python 3 machen, das auch für andere Betriebssysteme funktionieren sollte. Stellen Sie nach dem Testen sicher, dass Sie die Zeile auskommentieren, in der die Dateien tatsächlich entfernt werden.

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)
jftuga
quelle
4

Ich weiß nichts über die "500 neuesten", aber mit find können Sie Dinge löschen, die älter als X Minuten / Tage sind. Beispiel für Datei und älter als 2 Tage:

find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \;

Testen Sie zuerst mit:

find foo/ -mtime +2 -a -type f -exec ls -al \{\} \;

Beachten Sie die Backslashes und das Leerzeichen vor "\;". Weitere Informationen finden Sie auf der Manpage zum Suchen.

AndreasM
quelle
Das "(sagen wir) 500 neueste" ist hier die Essenz, daher sehe ich nicht, wie dies die ursprüngliche Frage beantwortet.
Peter John Acklam
Entschuldigung, war mir nicht klar.
AndreasM
3

Wenn Sie Dateien x Tage / Stunden alt halten könnten, anstatt die neueste x-Nummer, könnten Sie dies einfach mit tun tmpwatch --ctime 7d

Sirex
quelle
2

Ich denke, die -mtimeund -newerBefehlsoptionen findsind nützlich für Sie. Sie können man findfür weitere Informationen sehen.

Khaled
quelle
0

Warum nicht diesen einfacheren Code verwenden:

$ ls -t1 foo/| xargs -d '\n' rm --
eppesuig
quelle
1
Wie werden dadurch alle Dateien außer den 500 neuesten Dateien entfernt? Und wie geht das mit Unterverzeichnissen um? Ich denke, Sie haben den ursprünglichen Beitrag möglicherweise falsch verstanden.
Peter John Acklam