Löschen Sie alle Dateien (mit Ausnahme der vier neuesten) in allen Verzeichnissen mithilfe eines Bash-Skripts

7

Ich suche nach einem Bash-Skript, das in eine Liste von Verzeichnissen aufgenommen wird und alle bis auf die vier zuletzt erstellten Dateien löscht.

Wie kann ich das machen?

Marv1n
quelle
Wie aktuell ist neu? Ist es ein vordefinierter Zeitraum?
Bahamat
Möchten Sie, dass das Skript die vier neuesten Dateien gemäß der gesamten Liste der Verzeichnisse oder einzeln für jedes Verzeichnis aufbewahrt? Möchten Sie auch, dass es rekursiv arbeitet?
artistoex
Ich möchte, dass der Befehl rm in jeden Ordner geht und alle bis auf 4 (der neuesten Dateien)
löscht

Antworten:

6
ls -t | sed '1,4d' | xargs echo rm

Entfernen echoSie das gewünschte Ergebnis, wenn Sie zufrieden sind.

Wenn Sie Dateinamen mit Leerzeichen haben, ist mehr Arbeit erforderlich.

Glenn Jackman
quelle
Hey Kumpel, führte diesen Befehl aus, aber er listete nur die Verzeichnisnamen auf
Marv1n
3
Wir können ersetzen sed '1,4d'mit tail -n +5.
jfg956
@ Marvin, hast du irgendwelche Aliase, wie zum Beispiel für ls?
Glenn Jackman
1
@ Marvin: Entfernen Sie das Echo wie in der Antwort erläutert.
Stéphane Gimenez
0

Möchten Sie die vier neuesten Dateien in jedem Verzeichnis oder die vier neuesten Dateien in JEDEM Verzeichnis behalten?

Um das erste Problem zu lösen, verwenden Sie find, um jedes Verzeichnis aufzulisten, und entfernen dann in jedem Verzeichnis alle bis auf die vier neuesten Dateien. Das ist nicht zu schwer.

Die Lösung des zweiten Problems erfordert etwas mehr Überlegungen, ist aber tatsächlich einfacher zu schreiben.

Grundsätzlich finden Sie jede Datei rekursiv. Rufen Sie den Befehl "stat" auf und geben Sie die Änderungszeit und den Namen der Datei zurück. Sortieren Sie diese absteigend numerisch und überspringen Sie die ersten vier Dateien, die die neuesten sind.

Entfernen Sie dann die führenden Zeitstempel und die resultierende Liste der Dateinamen.

So etwas wie (ungetestet):

#!/bin/bash

find "$@" -type f -print0 \
| xargs -0 stat -c$'%Y\t%n' \
| sort -rn \
| awk -F$'\t' 'NR > 4 {print $2}' \
| while read f; do
    echo rm -v "${f}"
  done

Dies sollte funktionieren, obwohl Sie das 'Echo' in der while-Schleife entfernen möchten, um es effektiv zu machen. Testen Sie es zuerst sorgfältig!

ZILjr
quelle
Danke für die Antwort! Ich möchte 4 neueste Dateien in jedem Verzeichnis behalten. Grundsätzlich ist es ein Sicherungsordner für verschiedene Websites, die ich verwalte. Jeder Ordner ist eine Website. Ich habe ein tägliches Backup-Skript, das jede Site (einschließlich der Datenbank) in eine nette kleine JPA-Datei zerreißt.
März
Hey Kumpel, ich habe dieses Skript ausgeführt, aber es hat es geschafft, die meisten Dateien in jedem Unterordner zu löschen, um zusätzliche Informationen zu erhalten. Ich habe das Skript in / backup / und der Rest des Ordners ist wie gezeigt / backup / website1 / file1 / Backup / Website1 / Datei2 / Backup / Website1 / Datei3 / Backup / Website2 / Datei1 / Backup / Website2 / Datei2 / Backup / Website2 / Datei3 / Backup / Website2 / Datei4 und so weiter und so fort
Marv1n
0

Mir ist klar, dass dies nicht ganz das ist, wonach Sie fragen, aber für diese Art der Sicherung ziehe ich es vor, die Protokolldateien zu drehen, bevor Sie die neue erstellen. Es ist etwas expliziter und viel einfacher zu codieren:

#!/bin/bash

#Archive old backups
move () {
  if [ -e $1 ]
  then
    echo "Archiving old backups: $1 to $2"
    mv -f $1 $2 || echo "FAILED"
  fi
}

#Bump each backup +1
rm -rf backup.4
move backup.3.tgz backup.4.tgz
move backup.2.tgz backup.3.tgz
move backup.1.tgz backup.2.tgz
move backup.tgz backup.1.tgz

#Now create today's backup
...
ed.
quelle
0

Dieser Befehl sollte funktionieren

find PATH1 PATH2 PATH3 -type f  -printf '%T@ %p\n'|sort -nr|tail -n+5|cut -f 2- -d " "|xargs -i rm {}

Wenn Sie nicht möchten, dass der Befehl Dateien rekursiv löscht, fügen Sie die Option -maxdepth 1zuvor hinzu-type f

Der Befehl druckt rekursiv jede Datei mit ihrem letzten Änderungsdatum ( find PATH1 PATH2 PATH3 -type f -printf '%T@ %p\n'), sortiert die Liste nach Datum ( sort -nr) und überspringt dann die ersten vier Einträge ( tail -n+5). Schließlich wird die Zeitinformation gelöscht ( cut -f 2- -d " ") und das Ergebnis anschließend an xargs übergeben, das den entsprechenden Befehl rm generiert und ausführt.

artistoex
quelle
0

Die einfachste Methode:

for d in dir1 dir2 dir3; do
  rm -vf `ls -1t $d | head -n-4` 
done
Zarick Lau
quelle