Entfernen Sie die ältesten Dateien

9

Ich versuche alte Dateien aus dem Verzeichnis zu löschen und nur 3 neueste Dateien zu belassen.

cd /home/user1/test

while [ `ls -lAR | grep ^- | wc -l` < 3 ] ; do

    rm `ls -t1 /home/user/test | tail -1`
    echo " - - - "

done

Mit der bedingten Aussage stimmt etwas nicht.

d3vil0
quelle

Antworten:

9

Wenn Sie Dateien durchlaufen möchten, verwenden Sie niemalsls *. tl; dr Es gibt viele Situationen, in denen Sie am Ende die falsche Datei oder sogar alle Dateien löschen würden.

Leider ist dies in Bash eine schwierige Sache. Bei einer noch älteren find_date_sorteddoppelten Frage gibt es eine funktionierende Antwort, die Sie mit kleinen Änderungen verwenden können:

counter=0
while IFS= read -r -d '' -u 9
do
    let ++counter
    if [[ counter -gt 3 ]]
    then
        path="${REPLY#* }" # Remove the modification time
        echo -e "$path" # Test
        # rm -v -- "$path" # Uncomment when you're sure it works
    fi
done 9< <(find . -mindepth 1 -type f -printf '%TY-%Tm-%TdT%TH:%TM:%TS %p\0' | sort -rz) # Find and sort by date, newest first

* Nichts für ungut Jungs - ich habe es auch schon mal benutzt ls. Aber es ist wirklich nicht sicher.

Bearbeiten: Neufind_date_sorted bei Unit-Tests.

l0b0
quelle
Ich stimme dem Teil zu, in dem es darum geht, ls nicht zu analysieren. Auch das Skript ist ordentlich, aber ich denke, es könnte in einem
Einzeiler gemacht werden
Nun, Sie können Bash-Code immer in einen
Einzeiler komprimieren
2
Wenn ich @ Peter.O gnadenlos eine Idee stehlen darf, versuchen Sie es ((++counter>3))als Test. Es ist schön prägnant. Was Oneliner betrifft: Wenn es um Kürze geht, wickeln Sie den Code in eine Funktion ein, und machen Sie sich darüber keine Sorgen.
Sorpigal
@Sorpigal Ordentliche Abkürzung
l0b0
5

Um alle bis auf die 3 neuesten Dateien mit einem zsh-Glob zu löschen, können Sie mit Om(Großbuchstabe O) die Dateien vom ältesten zum neuesten und mit einem Index die gewünschten Dateien abrufen.

rm ./*(Om[1,-4])
#    | ||||  ` stop at the 4th to the last file (leaving out the 3 newest)
#    | |||` start with first file (oldest in this case)
#    | ||` subscript to pick one or a range of files
#    | |` look at modified time
#    | ` sort in descending order
#    ` start by looking at all files

Andere Beispiele:

# delete oldest file (both do the same thing)
rm ./*(Om[1])
rm ./*(om[-1])

# delete oldest two files
rm ./*(Om[1,2])

# delete everything but the oldest file
rm ./*(om[1,-2])
Mario Lopez
quelle
5

Die mit Abstand einfachste Methode besteht darin, zsh und seine Glob-Qualifikationsmerkmale zu verwenden : Omnach abnehmendem Alter (dh dem ältesten zuerst) zu sortieren und [1,3]nur die ersten drei Übereinstimmungen beizubehalten.

rm ./*(Om[1,3])

Weitere Beispiele finden Sie unter Wie filtere ich einen Glob in zsh?

Und tun Beachtung l0b0 Rat : Ihr Code brechen schrecklich , wenn Sie Dateinamen, die Shell - Sonderzeichen enthalten.

Gilles 'SO - hör auf böse zu sein'
quelle
Woa woa halt den Zug, ist das wirklich eine Komplettlösung in 1 Linie?
MetaGuru
2
@ Ryan Das ist zsh für dich.
Gilles 'SO - hör auf böse zu sein'
1

Mit der folgenden Funktion können Sie die neueste Datei in einem Verzeichnis abrufen:

newest_in() 
{ 
    local newest=$1

    for f;do [[ $f -nt $newest ]] && newest="$f"; done;

    printf '%s\n' "$newest"
}

Geben Sie ihm einen anderen Satz von Dateien, indem Sie nach jeder Iteration die neueste Datei exzudieren.

Tipp: Wenn Sie den ersten Satz von Dateien in einem Array mit dem Namen "$ {files [@]}" speichern, speichern Sie den Index der zuletzt gefundenen Datei und unset 'files[index]'vor der nächsten Iteration.

Verwendungszweck: newest_in [set of files/directories]

Beispielausgabe:

[rany$] newest_in ./*
foo.txt
[rany$]
Rany Albeg Wein
quelle
-1

Erstens ist die -ROption die Rekursion, was wahrscheinlich nicht das ist, was Sie wollen - das wird auch in allen Unterverzeichnissen gesucht. Zweitens dient der <Operator (wenn er nicht als Umleitung angesehen wird) dem Zeichenfolgenvergleich. Sie wollen wahrscheinlich -lt. Versuchen:

while [ `ls -1A | grep ^- | wc -l` -lt 3 ]

Aber ich würde hier finden:

while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]
Arcege
quelle
Beide schlagen fehl, wenn einer oder mehrere der Dateinamen ein '$ \ n' enthalten.
Rany Albeg Wein
-1

Ich weiß, es ist eine Sünde zu analysieren ls, aber was ist damit:

find . -type f -maxdepth 1 | xargs ls -ltr | sed '1,3d' | awk '{print $9}' | xargs rm

Ein schneller Test mit 5 leeren Dateien:

$ >1
$ >2
$ >3
$ >4
$ >5
$ find . -type f -maxdepth 1 | xargs ls -lt | sed '1,3d' | awk '{print $9}' | xargs rm
$ ls -1
3
4
5
Rudolf Adamkovic
quelle
Dieser wird aus zwei Gründen fehlschlagen: Analysieren der lsAusgabe und Verwenden findund xargsZusammen in der falschen Weise. Wenn Sie kombinieren findund xargsich empfehle Ihnen, finds -print0und entsprechend xargss -OOptionen zu verwenden. Weitere Informationen zum Thema finden Sie unter Verwenden von Suchen . Vielleicht möchten Sie auch einen Blick darauf werfen und lesen, warum das Parsen von ls sehr schlecht ist.
Rany Albeg Wein
-2

Dieser Einzeiler macht alles, was ich denke:

ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"
Salve
quelle
ls ist ein Tool zum interaktiven Anzeigen von Dateiinformationen. Die Ausgabe ist für Menschen formatiert und führt zu Fehlern in Skripten. Verwenden Sie stattdessen Globs oder Find. Verstehe warum: mywiki.wooledge.org/ParsingLs
Rany Albeg Wein
-2

Hier ist eine Lösung:

rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)
Babak
quelle
1
@bakbak ls ist ein Tool zum interaktiven Anzeigen von Dateiinformationen. Die Ausgabe ist für Menschen formatiert und führt zu Fehlern in Skripten. Schauen Sie hier, um zu verstehen, warum . Speziell wenn Sie über Ihre Antwort sprechen - diese wird unterbrochen, wenn eine oder mehrere der Dateien ein $ '\ n' Zeichen enthalten. Außerdem fehlen der Befehlssubstitution (dh $ (...)) doppelte Anführungszeichen, was ein weiteres wichtiges Thema aufwirft - das Teilen von Wörtern !
Rany Albeg Wein