Script Bash: elimine condicionalmente archivos más antiguos manteniendo las copias más recientes

Script Bash: elimine condicionalmente archivos más antiguos manteniendo las copias más recientes

Nota: aunque hay una respuesta de jeff-schaller, depende de zsh; entonces me gustaría obtener una respuesta basada en Bash.

Me gusta crear un script Bash para eliminar condicionalmente archivos más antiguos de un directorio de respaldo.

Hay 2 condiciones para 2 copias de seguridad de archivos distintos:

1. Conserve la última copia Edge_Profile_*.tgzy elimine el resto.Edge_Profile_*.tgz solo si tienen más de 5 días.

2. Conserve la última copia Firefox_Profile_*.tgzy elimine el resto Firefox_Profile_*.tgz.no importa la edad que tengan.

Así es como modifiqué esta respuesta de AskUbuntu:https://askubuntu.com/a/933098/928088

Guion:

#!/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;

Salida en el archivo de registro con 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
....

Salida en el archivo de registro mientras se ejecuta el script, sin 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
....

Archivos totales en el directorio: 20 archivos

1, Edge_Profile_*.tgz: Del 6 de julio al 17 de julio: 12 archivos

2, Firefox_Profile_*.tgz: Del 1 al 8 de julio: 8 archivos

Los problemas:

(1) yopensarEl guión funciona, pero no estoy seguro porque lo modifiqué en su mayor parte sin saber qué está pasando.

(2) Salida al archivo de registro:

Preferiría exactamente el mismo resultado en el archivo de registro que obtengo echo, excepto solo los nombres de los archivos (no con la ruta completa), como:

rm Edge_Profile_Jul_11_2021_00-35.tgz

skipping Edge_Profile_Jul_12_2021_00-35.tgz (too new)

SO: Ubuntu MATE 21.04

Muchas gracias.

Respuesta1

Manipular archivos en función de sus tiempos de modificación es mucho más fácil en un shell que le permite acceder a ellos directamente. zsh es uno de esos shells. Simplemente sudo apt install zshpara instalarlo. Dado que sus archivos parecen estar en un directorio, esta respuesta no es recursiva. Demostrando primero el caso más simple:

  • Para conservar la copia más reciente de Firefox_Profile_*.tgz y eliminar el resto sin importar su antigüedad:

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

    Retire la echo wouldporción si se ve correcta. Esto utiliza uncalificador glob (comodín)dentro del paréntesis para hacer tres cosas:

    • seleccione solo archivos simples (no directorios, sockets, etc.) con.
    • ordenar (ordenar) los archivos por su hora de modificación, del más nuevo al más antiguo, conom
    • seleccione una porción de la lista resultante comenzando desde el segundo elemento hasta el final, omitiendo el primer archivo (el más nuevo), con[2,-1]

    Si no hay archivos coincidentes, zsh se detendrá y se quejará con "zsh: no se encontraron coincidencias" y no ejecutará el archivo rm.

  • Para conservar la última copia de Edge_Profile_*.tgz y eliminar el resto solo si tienen más de 5 días, primero tomamos la última:

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

    ... y luego obtenemos los que tienen más de cinco días:

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

    La parte nueva aquí está +5en el mmodificador. Eso selecciona archivos que tienen más de 5 días. Después de eso, nos aseguramos de que el más nuevo no esté en la lista para eliminar:

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

    La parte nueva aquí es el símbolo de resta de matriz.:| ; está documentado en elSección de expansión de parámetros del manual de zsh. Selecciona los elementos de "más antiguos" que no están en "más nuevos". Finalmente, eliminamos esa lista de archivos:

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

información relacionada