Como excluir backups antigos com base em uma data no nome do arquivo?

5

Eu tenho um backup diário chamado assim:

yyyymmddhhmm.zip // pattern
201503200100.zip // backup from 20. 3. 2015 1:00

Estou tentando criar um script que exclua todos os backups com mais de três dias. O script também deve ser capaz de excluir todos os outros arquivos na pasta que não correspondam ao padrão (mas haveria uma opção para isso no script para desabilitar isso).

Para determinar a idade do arquivo, não quero usar os timestamps de backups, pois outros programas também manipulam os arquivos e podem ser adulterados.

Com a ajuda de: Remove arquivos com mais de 5 dias no UNIX (data no nome do arquivo, não timestamp) Eu tenho:

#!/bin/bash

DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups/
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)

ls -1 ${BACKUPS_PATH}????????????.zip |
  while read A DATE B FILE
  do
     [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
  done

if [ $DELETE_OTHERS == "yes" ]; then
    rm ${BACKUPS_PATH}*.* // but I don't know how to not-delete the files matching pattern
fi

Mas continua dizendo:

rm: missing operand

Onde está o problema e como completar o script?

    
por Joudicek Jouda 21.03.2015 / 16:42

3 respostas

6

O primeiro problema no seu código é que você está analisando ls . Isso significa que ele quebrará com muita facilidade, se você tiver espaços em seus nomes de arquivos ou diretórios, por exemplo. Você deve usar o shell globbing ou find .

Um problema maior é que você não está lendo os dados corretamente. Seu código:

ls -1 | while read A DATE B FILE

nunca preencherá $FILE . A saída de ls -1 é apenas uma lista de nomes de arquivos, portanto, a menos que esses nomes de arquivo contenham espaço em branco, somente a primeira das quatro variáveis que você fornecer a read será preenchida.

Aqui está uma versão funcional do seu script:

#!/usr/bin/env bash

DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)

## Find all files in $BACKUPS_PATH. The -type f means only files
## and the -maxdepth 1 ensures that any files in subdirectories are
## not included. Combined with -print0 (separate file names with 
ls -1 | while read A DATE B FILE
), ## IFS= (don't break on whitespace), "-d ''" (records end on '
#!/usr/bin/env bash

DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)

## Find all files in $BACKUPS_PATH. The -type f means only files
## and the -maxdepth 1 ensures that any files in subdirectories are
## not included. Combined with -print0 (separate file names with %pre%),
## IFS= (don't break on whitespace), "-d ''" (records end on '%pre%') , it can
## deal with all file names.
find ${BACKUPS_PATH} -maxdepth 1 -type f -print0  | while IFS= read -d '' -r file
do
    ## Does this file name match the pattern (13 digits, then .zip)?
    if [[ "$(basename "$file")" =~ ^[0-9]{12}.zip$ ]]
    then
        ## Delete the file if it's older than the $THR
        [ "$(basename "$file" .zip)" -le "$THRESHOLD" ] && rm -v -- "$file"
    else
        ## If the file does not match the pattern, delete if 
        ## DELETE_OTHERS is set to "yes"
        [ $DELETE_OTHERS == "yes" ] && rm -v -- "$file"
    fi
done
') , it can ## deal with all file names. find ${BACKUPS_PATH} -maxdepth 1 -type f -print0 | while IFS= read -d '' -r file do ## Does this file name match the pattern (13 digits, then .zip)? if [[ "$(basename "$file")" =~ ^[0-9]{12}.zip$ ]] then ## Delete the file if it's older than the $THR [ "$(basename "$file" .zip)" -le "$THRESHOLD" ] && rm -v -- "$file" else ## If the file does not match the pattern, delete if ## DELETE_OTHERS is set to "yes" [ $DELETE_OTHERS == "yes" ] && rm -v -- "$file" fi done
    
por 21.03.2015 / 18:38
0

não se esqueça da linha sed entre ls -1 e while read , esta linha é importante.

para a primeira pergunta, gostaria de sugerir: (um remplacement do awk, não consegui encontrar um equivalente sed)

ls -1 ${BACKUPS_PATH}????????????.zip |\
  awk -F. '{printf "%s %s\n",$1,$0 ;}' |\
  while read DATE FILE
  do
     [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
  done

desde que a aritmética do shell seja pelo menos de 37 bits para fazer o teste $DATE -le $THRESHOLD .

    
por 21.03.2015 / 17:50
0

No uso do FreeBSD: Exemplo: encontre todos os arquivos em / usr / home / foobar pertencentes a foobar com mais de 5760 minutos (4 dias) e exclua-os.

find /usr/home/foobar -user foobar -type f -mmin +5760 -delete
    
por 19.11.2018 / 17:40