Lösung ohne Probleme mit "ls" (seltsam benannte Dateien)
Dies ist eine Kombination aus der Antwort von Ceving und Anubhava. Beide Lösungen funktionieren bei mir nicht. Da ich nach einem Skript suchte, das jeden Tag zum Sichern von Dateien in einem Archiv ausgeführt werden sollte, wollte ich Probleme mit ls
vermeiden (Jemand könnte eine komisch benannte Datei in meinem Sicherungsordner gespeichert haben). Also habe ich die genannten Lösungen an meine Bedürfnisse angepasst.
Meine Lösung löscht alle Dateien, außer die drei neusten Dateien.
find . -type f -printf '%[email protected]\t%p\n' |
sort -t $'\t' -g |
head -n -3 |
cut -d $'\t' -f 2- |
xargs rm
Einige Erklärungen:
find
listet alle Dateien (nicht Verzeichnisse) im aktuellen Ordner auf. Sie werden mit Zeitstempel ausgedruckt.
sort
sortiert die Zeilen nach Zeitstempel (älteste oben).
head
druckt die obersten Zeilen bis zu den letzten 3 Zeilen.
cut
entfernt die Zeitstempel.
xargs
läuft rm
für jede ausgewählte Datei.
Damit Sie meine Lösung überprüfen können:
(
touch -d "6 days ago" test_6_days_old
touch -d "7 days ago" test_7_days_old
touch -d "8 days ago" test_8_days_old
touch -d "9 days ago" test_9_days_old
touch -d "10 days ago" test_10_days_old
)
Dadurch werden im aktuellen Ordner 5 Dateien mit unterschiedlichen Zeitstempeln erstellt. Führen Sie zuerst dieses Skript aus und dann den Code zum Löschen alter Dateien.
Dies listet alle Dateien außer den neuesten drei auf:
ls -t | tail -n +4
Dadurch werden diese Dateien gelöscht:
ls -t | tail -n +4 | xargs rm --
Dies listet auch dotfiles auf:
ls -At | tail -n +4
und mit dotfiles löschen:
ls -At | tail -n +4 | xargs rm --
Aber Achtung:ls
parsen kann gefährlich sein, wenn die Dateinamen komische Zeichen wie Zeilenumbrüche oder Leerzeichen enthalten. Wenn Sie sicher sind, dass Ihre Dateinamen keine komischen Zeichen enthalten, dann parsen Sie ls
ist ziemlich sicher, umso mehr, wenn es sich um ein einmaliges Skript handelt.
Wenn Sie ein Skript zur wiederholten Verwendung entwickeln, sollten Sie die Ausgabe von ls
auf keinen Fall parsen und verwenden Sie die hier beschriebenen Methoden:http://mywiki.wooledge.org/ParsingLs
ls -t | tail -n +4 | xargs -I {} rm {}
Wenn Sie einen Einzeiler wünschen
Das Folgende sieht etwas kompliziert aus, ist aber sehr vorsichtig, um korrekt zu sein, selbst bei ungewöhnlichen oder absichtlich böswilligen Dateinamen. Leider erfordert es GNU-Tools:
count=0
while IFS= read -r -d ' ' && IFS= read -r -d '' filename; do
(( ++count > 3 )) && printf '%s\0' "$filename"
done < <(find . -maxdepth 1 -type f -printf '%[email protected] %P\0' | sort -g -z) \
| xargs -0 rm -f --
Erläuterung, wie das funktioniert:
- Suchen gibt
<mtime> <filename><NUL>
aus für jede Datei im aktuellen Verzeichnis. sort -g -z
führt eine allgemeine numerische Sortierung (Gleitkomma, im Gegensatz zu Ganzzahlen) basierend auf der ersten Spalte (Zeiten) durch, wobei die Zeilen durch NULs getrennt sind.- Die erste
read
imwhile
loop entfernt die mtime (wird nachsort
nicht mehr benötigt fertig). - Der zweite
read
imwhile
Schleife liest den Dateinamen (läuft bis zur NUL). - Die Schleife erhöht einen Zähler und überprüft ihn dann; Wenn der Status des Zählers anzeigt, dass wir das anfängliche Überspringen überschritten haben, geben wir den Dateinamen aus, getrennt durch eine NUL.
xargs -0
hängt dann diesen Dateinamen an die argv-Liste an, die es sammelt, umrm
aufzurufen mit.