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.

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.


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

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.


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$]

-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 ]

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

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 -- "{}"

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)

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.