Cleaner way to delete files on Linux which include a datestamp as part of file name

I have a new requirement to purge MySQL dump files that are older than 30 days. The files use a naming convention of “all-mysql-YYYYMMDD-HHMM.dump”. The files are located on SAN mounted file system, so restoration is not an issue, but the drive space is limited unfortunately and fills up quickly so it requires frequent human intervention.

Example of files names

  • all-mysql-20130324-2330.dump
  • all-mysql-20130325-2330.dump
  • all-mysql-20130326-2330.dump

My first thought was to use “find” inside a batch script with -mtime +30, however, the modification times cannot be guaranteed and some of the older archives could evade the purge date 🙂

I created the following BASH script, but I was hoping there was there was a cleaner way to perform this operation.

#!/bin/bash

STARTING_DIR=$(pwd)

FILE_PREFIX=all-mysql-
BACKUP_DIR=/opt/backup/mysql/dumps
ARCHIVE_WINDOW_DAYS=30

cd $BACKUP_DIR

# Create YYYYMMDD datestamp for Today - $ARCHIVE_WINDOW_DAYS
ARCHIVE_WINDOW_IN_SECS=$(echo "$(date +%s) - (${ARCHIVE_WINDOW_DAYS} * 86400)" | bc)
PURGE_BEFORE_DATE=$(date -d @${ARCHIVE_WINDOW_IN_SECS} +%Y%m%d)

for backup_file in $FILE_PREFIX*
do
    # Trim prefix, time portion of date stamp, and file extension
    # from $backup_file to allow numeric comparison against YYYYMMDD
    backup_trim_tmp=${backup_file#${FILE_PREFIX}}
    backup_trimmed=${backup_trim_tmp%-****.dump}

    if [ ${PURGE_BEFORE_DATE} -gt ${backup_trimmed} ]
    then
        rm $backup_file
    fi
done

cd $STARTING_DIR

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Another way to delete all except the last 30 files:

rm $(ls -r | tail -n +31)

Or here is a shorter version of the script in the original post:

cd /opt/backup/mysql/dumps
d=$(date -r $(($(date +%s)-30*86400)) +%Y%m%d)
for f in all-mysql-*; do
    [[ ${f#all-mysql-} < $d ]] && rm $f
done

Method 2

If you want to delete all except for the last 30 files:

rm `echo " " all-mysql-*.dump | sed -r -e 's/( [^ ]+){0,30}$//'`

That would fulfill your requirement provided that there is one backup per day, and the naming scheme stays the way it is (i.e. alphabetical order = chronological order, no spaces in filenames).

You specifically requested a one-liner in one of your comments. Personally I like to write things out more. This one liner is a bit on the dangerous side (if the sed fails, everything is deleted).


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x