Script Bash: exclua condicionalmente arquivos mais antigos, mantendo as cópias mais recentes

Script Bash: exclua condicionalmente arquivos mais antigos, mantendo as cópias mais recentes

Nota: Embora haja uma resposta de Jeff-Schaller, isso depende zsh; então eu gostaria de obter uma resposta com base em Bash.

Gosto de criar um script Bash para excluir condicionalmente arquivos mais antigos de um diretório de backup.

Existem 2 condições para 2 backups de arquivos distintos:

1, mantenha a cópia mais recente Edge_Profile_*.tgze exclua o restanteEdge_Profile_*.tgz somente se tiverem mais de 5 dias.

2, Mantenha a cópia mais recente Firefox_Profile_*.tgze exclua o restante Firefox_Profile_*.tgz,não importa quantos anos eles têm.

Veja como modifiquei esta resposta do AskUbuntu:https://askubuntu.com/a/933098/928088

Roteiro:

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

Saída no arquivo de log com 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
....

Saída no arquivo de log durante a execução do script, sem 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
....

Total de arquivos no diretório: 20 arquivos

1, Edge_Profile_*.tgz: De 06 a 17 de julho: 12 arquivos

2, Firefox_Profile_*.tgz: De 01 a 08 de julho: 8 arquivos

As questões:

(1) eupensaro script está funcionando, mas não tenho certeza, pois modifiquei a maior parte sem saber o que está acontecendo.

(2) Saída para arquivo de log:

Eu preferiria exatamente a mesma saída no arquivo de log que obtenho echo, exceto apenas os nomes dos arquivos (não com o caminho completo), 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

Muito obrigado.

Responder1

Manipular arquivos com base em seus tempos de modificação é muito mais fácil em um shell que permite acessá-los diretamente. zsh é um desses shells. Simplesmente sudo apt install zshpara instalá-lo. Como seus arquivos parecem estar em um diretório, esta resposta não é recursiva. Demonstrando primeiro o caso mais simples:

  • Para manter a cópia mais recente do Firefox_Profile_*.tgz e excluir o restante, independentemente da idade:

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

    Remova a echo wouldparte se parecer correta. Isso usa umqualificador glob (curinga)entre parênteses para fazer três coisas:

    • selecione apenas arquivos simples (não diretórios ou soquetes ou etc) com.
    • ordene (classifique) os arquivos pela hora de modificação, do mais novo para o mais antigo, comom
    • selecione uma fatia da lista resultante começando do segundo elemento até o final - ignorando o primeiro arquivo (mais recente), com[2,-1]

    Se não houver arquivos correspondentes, o zsh irá parar e reclamar com "zsh: nenhuma correspondência encontrada" e não executará o arquivo rm.

  • Para manter a cópia mais recente de Edge_Profile_*.tgz e excluir o restante apenas se tiverem mais de 5 dias, primeiro pegamos a mais recente:

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

    ... e então temos aqueles que têm mais de cinco dias:

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

    A nova parte aqui é +5o mmodificador. Isso seleciona arquivos com mais de 5 dias. Depois disso, garantimos que o mais novo não esteja na lista para remoção:

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

    A nova parte aqui é o símbolo de subtração de array :|; está documentado noSeção de expansão de parâmetros do manual zsh. Seleciona os elementos de “mais antigos” que não estão em “mais novos”. Finalmente, removemos essa lista de arquivos:

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

informação relacionada