Bash-Skript: Ältere Dateien bedingt löschen und dabei die neuesten Kopien behalten

Bash-Skript: Ältere Dateien bedingt löschen und dabei die neuesten Kopien behalten

Hinweis: Es gibt zwar eine Antwort von Jeff-Schaller, aber diese hängt von ab zsh. Ich würde daher gerne eine Antwort basierend auf erhalten Bash.

Ich möchte ein Bash-Skript erstellen, um ältere Dateien bedingt aus einem Sicherungsverzeichnis zu löschen.

Es gibt zwei Bedingungen für zwei unterschiedliche Dateisicherungen:

1. Behalten Sie die neueste Kopie von Edge_Profile_*.tgzund löschen Sie den Rest vonEdge_Profile_*.tgz nur wenn sie älter als 5 Tage sind.

2. Behalten Sie die neueste Kopie von Firefox_Profile_*.tgzund löschen Sie den Rest von Firefox_Profile_*.tgz.egal wie alt sie sind.

So habe ich diese AskUbuntu-Antwort geändert:https://askubuntu.com/a/933098/928088

Skript:

#!/bin/bash

LOG_FILE="/home/admn/Cleanup.log"
TEMP_LOG="/tmp/Temp_Cleanup.log"

mv $LOG_FILE $TEMP_LOG

{

cd /home/admn/Downloads/Test;

echo "Cleanup log:" `date`

find /home/admn/Downloads/Test/Edge_Profile_*.tgz -type f \( -mtime +5 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac;
done

echo

find /home/admn/Downloads/Test/Firefox_Profile_*.tgz -type f \( -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac        
done

} &>> $LOG_FILE

cat $TEMP_LOG >>$LOG_FILE

exit;

Ausgabe im Logfile mit echo:

/usr/local/scripts/cleanup.sh

rm /home/admn/Downloads/Test/Edge_Profile_Jul_06_2021_00-35.tgz
rm /home/admn/Downloads/Test/Edge_Profile_Jul_07_2021_00-35.tgz
....
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new)
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new)
....

rm /home/admn/Downloads/Test/Firefox_Profile_Jul_01_2021_00-35.tgz
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_02_2021_00-35.tgz
....

Ausgabe im Logfile während der eigentlichen Ausführung des Skripts, ohne echo:

/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new): No such file or directory
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new): No such file or directory
....

Gesamtzahl der Dateien im Verzeichnis: 20 Dateien

1, Edge_Profile_*.tgz: Vom 06. Juli bis 17. Juli: 12 Dateien

2, Firefox_Profile_*.tgz: Vom 01. Juli bis 08. Juli: 8 Dateien

Die Probleme:

(1) Ichdenkendas Skript funktioniert irgendwie, aber ich bin nicht sicher, da ich die meisten Teile geändert habe, ohne zu wissen, was vor sich geht.

(2) Ausgabe ins Logfile:

Ich würde in der Protokolldatei lieber genau dieselbe Ausgabe haben, die ich mit bekomme echo, nur mit den Dateinamen (nicht mit vollständigem Pfad), etwa:

rm Edge_Profile_Jul_11_2021_00-35.tgz

skipping Edge_Profile_Jul_12_2021_00-35.tgz (too new)

Betriebssystem: Ubuntu MATE 21.04

Vielen Dank.

Antwort1

Das Bearbeiten von Dateien anhand ihrer Änderungszeitpunkte ist in einer Shell, die Ihnen direkten Zugriff darauf ermöglicht, viel einfacher. zsh ist eine solche Shell. sudo apt install zshInstallieren Sie sie einfach. Da Ihre Dateien in einem Verzeichnis zu liegen scheinen, ist diese Antwort nicht rekursiv. Zuerst wird der einfachere Fall demonstriert:

  • So behalten Sie die neueste Kopie von Firefox_Profile_*.tgz und löschen den Rest, unabhängig vom Alter:

    echo would rm -v -- Firefox_Profile_*.tgz(.om[2,-1])
    

    Entfernen Sie den echo wouldTeil, wenn er richtig aussieht. Dies verwendet einGlob (Platzhalter)-Qualifiziererinnerhalb der Klammern, um drei Dinge zu tun:

    • Wählen Sie nur einfache Dateien aus (keine Verzeichnisse oder Sockets usw.) mit.
    • Sortieren Sie die Dateien nach dem Änderungszeitpunkt, vom neuesten zum ältesten, mitom
    • Wählen Sie einen Ausschnitt der resultierenden Liste aus, beginnend beim zweiten Element bis zum Ende - wobei die erste (neueste) Datei übersprungen wird, mit[2,-1]

    Wenn keine übereinstimmenden Dateien vorhanden sind, wird zsh angehalten und beschwert sich mit „zsh: keine Übereinstimmungen gefunden“ und führt die Datei nicht aus rm.

  • Um die neueste Kopie von Edge_Profile_*.tgz aufzubewahren und den Rest nur zu löschen, wenn sie älter als 5 Tage sind, greifen wir zuerst auf die neueste zu:

    newest=(Edge_Profile_*.tgz(.om[1]))
    

    ... und dann bekommen wir diejenigen, die älter als fünf Tage sind:

    older=(Edge_Profile_*.tgz(.m+5))
    

    Neu ist hier +5der Modifikator on m. Dieser wählt Dateien aus, die älter als 5 Tage sind. Danach stellen wir sicher, dass die neueste nicht in der Liste zum Entfernen ist:

    remove=("${(@)older:|newest}")
    

    Der neue Teil hier ist das Array-Subtraktionssymbol :|; es ist dokumentiert in derAbschnitt „Parametererweiterung“ im zsh-Handbuch. Es wählt die Elemente von „älter“ aus, die nicht in „neueste“ sind. Schließlich entfernen wir diese Dateiliste:

    echo would rm -v -- "${remove[@]}"
    

verwandte Informationen