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_*.tgz
e exclua o restanteEdge_Profile_*.tgz
somente se tiverem mais de 5 dias.
2, Mantenha a cópia mais recente Firefox_Profile_*.tgz
e 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 zsh
para 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 would
parte 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, com
om
- 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
.- selecione apenas arquivos simples (não diretórios ou soquetes ou etc) com
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 é
+5
om
modificador. 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[@]}"