1

every our backup files of a database are created. The files are named like this:

prod20210528_1200.sql.gz 
pattern: prod`date +\%Y%m%d_%H%M`

The pattern could be adjusted if needed.

I would like to have a script that:

  • keeps all backups for the last x (e.g. 3) days
  • for backups older than x (e.g. 3) days only the backup from time 00:00 shall be kept
  • for backups older than y (e.g. 14) days only one file per week (monday) shall be kept
  • for backups older than z days (e.g. 90) only one file per month (1st of each month) shall be kept
  • the script should rather use the filename instead of the date (created) information of the file, if that it possible
  • the script should run every day

Unfortunately, I have very little knowledge of the shell-/bash-script language. I would do something like this:

if (file < today - x AND date > today - (x + 1))
{
  if (%H_of_file != 00 AND %M_of_file != 00)
  {  
    delete file
  }
}

if (file < today - y AND date > today - (y + 1))
{
  if (file != Monday)
  {  
    delete file
  }
}

if (file < today - z AND date > today - (z + 1))
{
  if (%m_of_file != 01)
  {  
    delete file
  }
}

Does this makes any sense for you?

Thank you very much! 

All the best,
Phantom


1
  • find is very good for checking a files modification date [= creation date] so just for example, something like find pathname/ -type f -mtime +99 -exec ls {} \; could list all files which are at least 99 days old. May 28 at 20:18
0

This works for me (BSD date, not GNU date)

#!/usr/local/bin/bash
DIR_BACKUPS='/backups'
KEEP_DAILY=3
KEEP_WEEKLY=14
KEEP_MONTHLY=90

date_keep_daily=$(date -j -v-${KEEP_DAILY}d +"%Y%m%d")
date_keep_weekly=$(date -j -v-${KEEP_WEEKLY}d +"%Y%m%d")
date_keep_monthly=$(date -j -v-${KEEP_MONTHLY}d +"%Y%m%d")

for file in $DIR_BACKUPS/prod*.sql.gz; do
    timestamp=${file#*onwalt}
    timestamp=${timestamp%%.*}
    date_of_file=${timestamp%%_*}
    hour_of_file=${timestamp:(-4):2}
    
    if [[ $date_of_file < $date_keep_monthly ]]; then
        if [[ $(date -jf "%Y%m%d_%H%M" $timestamp +"%d") != 01 ]]; then
            rm $file
        fi
    elif [[ $date_of_file < $date_keep_weekly ]]; then
        if [[ $(date -jf "%Y%m%d_%H%M" $timestamp +"%u") != 1 ]]; then
            rm $file
        fi
    elif [[ $date_of_file < $date_keep_daily ]]; then
        if [[ $(date -jf "%Y%m%d_%H%M" $timestamp +"%H") != 00 ]]; then
            rm $file
        fi
    fi
done
````
2
  • date -j doesn't work for me. I'd suggest simplifying the whole thing by using UTC dates in a unix epoch form [seconds since 1970] since this makes date comparisons trivial. Jun 2 at 21:45
  • The script works for BSD date, not GNU date. GNU date should be something like $(date +%s --date="-30 days")
    – Phantom
    Jun 3 at 12:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.