5

I have a folder where I backup my databases to and I want to delete all backups created between 11 am and 3 pm and it doesn't matter what day it is -- this is the catch!

I found this command to be very helpful, but not in my use case:

find . -type f -newermt '01 nov 2018 00:00:00' -not -newermt '10 nov 2018 00:00:00' -delete

But here it forces me to an interval between two dates! I want to delete only backups created between two specific times.

2 Answers2

5

Simply enough, given that you tagged , you have the stat command available, which will extract a file's modification time, and the GNU date command, which will extract the hour from from a given time:

find . -type f -exec sh -c '
  h=$(date -d @$(stat -c %Y "$1") +%-H); [ "$h" -ge 11 ] && [ "$h" -lt 15 ]' \
  sh {} \; -ls

If the results look correct, then:

find . -type f -exec sh -c '
  h=$(date -d @$(stat -c %Y "$1") +%-H); [ "$h" -ge 11 ] && [ "$h" -lt 15 ]' \
  sh {} \; -delete

Here's a test-run with the -ls version:

$ touch -d 'Wed Sep 12 11:00:01 EDT 2018' 11am
$ touch -d 'Wed Sep 12 12:00:02 EDT 2018' 12pm
$ touch -d 'Wed Sep 12 15:00:03 EDT 2018' 303pm
$ find . -type f -exec sh -c 'h=$(date -d @$(stat -c %Y "$1") +%-H); [ "$h" -ge 11 ] && [ "$h" -lt 15 ]' sh {} \; -ls
1705096    0 -rw-r--r--   1 user group 0 Sep 12  2018 ./11am
1705097    0 -rw-r--r--   1 user group 0 Sep 12  2018 ./12pm

Credit to Kusalananda for writing the excellent answer I followed, at: Understanding the -exec option of `find`

Note that we do not want the {} + version of find here, as we want the -exec results to be per-file, so that we only delete files that match the time range.

The embedded shell script has two main pieces: determine the file's "hour" timestamp and then return success or failure based on the range. The first part is itself accomplished in two pieces. The variable is assigned the result of the command substitution; the command should be read inside-out:

  1. $(stat -c %Y "$1") -- this (second) command-substitution calls stat on the $1 parameter of the embedded shell script; $1 was assigned by find as one of the pathnames it found. The %Y option to the stat command returns the modification time in seconds-since-the-epoch.
  2. date -d @ ... +%-H -- this takes the seconds-since-the-epoch from the above command substitution and asks date to give us the Hours portion of that time; the @ syntax tells date that we're giving it seconds-since-the-epoch as an input format. With the - option in the date output format, we tell GNU date to not pad the value with any leading zeroes. This prevents any octal misinterpretation later.

Once we have the $h Hour variable assigned, we use bash's conditional operator [[ to ask whether that value is greater-than-or-equal to 11 and also strictly less than 15.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
0

Not ideal, but this might be useful.

find . -type f -print | while read l; do
    hour=$(stat -c "%z" ${l} | awk '{print $2}' | awk -F: '{print $1}')
    if [[ 11 -le ${hour} ]] && [[ ${hour} -le 15 ]]; do
      rm -f ${l}
    done
done
Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
Lewis M
  • 1,048