我使用一个简单的查找脚本来删除超过 30 天的备份 tar 文件,但为了保存历史并能够进一步回顾,我想切换到保留最近 15 天以及创建的所有备份每个月的第一天(12 个月)和每年的第一天(回溯 12 年)。完成此任务最优雅的方法是什么?
答案1
如果您的文件具有正确的文件系统级时间戳和日期包含在文件名中(例如backup-20230713.tar.gz
左右),然后是这样的:
# delete files older than 30 days, except ones from the first of each month
find . -name 'backup-*.tar.gz' -mtime +30 ! -name '*-??????01.tar.gz' -delete
# delete files older than a year, except ones from January 1st
find . -name 'backup-*.tar.gz' -mtime +366 ! -name '*-????0101.tar.gz' -delete
# delete everything older than 12 years:
find . -name 'backup-*.tar.gz' -mtime +$(( 12 * 366 )) -delete
或者,只需在创建文件时根据“组”将文件放置在单独的目录中,例如,每年的第一天位于yearly/
,类似地monthly/
,其余的位于daily/
。然后只需执行以下操作:
find daily/ -mtime +30 -delete
find monthly/ -mtime +366 -delete
find yearly/ -mtime +$((12 * 366)) -delete
在使用之前,您可能应该广泛测试类似的东西。 (使用等创建测试文件touch -d
并尝试find
不带等的命令-delete
)
答案2
免责声明:我是该书的当前作者生皮(右旋)此答案中使用的程序(位于https://github.com/raforg/rawhide)。
右旋(和寻找) 可以将修改时间与可以使用 精确指定修改时间的参考文件进行比较touch -t YYYYMMDDhhmm
。
下面是一个 shell 脚本,它 chdirs 到备份目录,并为过去 12 个月的每个月的第一天和过去 12 年的每年的一月的第一天创建带时间戳的参考文件。
然后它调用右旋列出文件(使用右旋的-l
选项)需要根据您的规范删除。
它有一个-D
选项可以删除文件(使用右旋的-UUU
选项)。
搜索条件首先定义一个辅助函数,当文件在给定日期(即给定时间和一天后之间)最后一次修改时,该函数返回 true:
on(givenday) { mtime >= givenday && mtime < givenday + day }
然后,搜索条件将匹配常规文件 ( f
),这些文件是 tar 文件 ( "*.tar*"
) 并且至少存在 15 天 ( old(15*days)
),并且上次修改日期不是过去十二个月中任何一个月的第一天,或者是第一个月过去十二年中任何一年的一月(例如,!on("1st00".mtime) && ...
)。
然后它会删除带时间戳的参考文件。
#!/bin/sh
# Delete backup tarfiles that are older than 15 days except those created
# on the 1st of the month for the past 12 months, and those created on the
# first of January for the past 12 years.
# usage: $0 [-D]
# The -D option deletes files. Without it, they are listed.
# Set this to the path to the backups
path=/path/to/backups
opts=-l
case "$1" in
-D)
opts="-UUU"
;;
?*)
echo usage: $0 [-D]
echo "The -D option deletes files (with exceptions)."
echo "Without it, they will be listed instead."
echo Files in $path will be listed or deleted.
exit 1
;;
esac
cd "$path" || exit 1
# Create timstamped reference files for the 1st Jan (past 12 years)
year=`date +%Y`
for i in 0 1 2 3 4 5 6 7 8 9 10 11 12
do
y=`expr $year - $i`
touch -t ${y}01010000 1stJan`printf %02d $i`
done
# Create timstamped reference files for the 1st of the month (past 12 months)
month=`date +%m`
for i in 0 1 2 3 4 5 6 7 8 9 10 11 12
do
touch -t $year${month}010000 1st`printf %02d $i`
if [ $month = 01 ]
then
month=12
year=`expr $year - 1`
else
month=`expr $month - 1`
month=`printf '%02d' $month`
fi
done
# Delete the backup tarfiles
rh $opts '
# Define a helper function to make the rest easier to read.
# True when mtime is on the given day.
on(givenday) { mtime >= givenday && mtime < givenday + day }
# Tar files at least 15 days old
f && "*.tar*" && old(15*days) &&
# Not last modified on the 1st of the past 12 months
!on("1st00".mtime) &&
!on("1st01".mtime) &&
!on("1st02".mtime) &&
!on("1st03".mtime) &&
!on("1st04".mtime) &&
!on("1st05".mtime) &&
!on("1st06".mtime) &&
!on("1st07".mtime) &&
!on("1st08".mtime) &&
!on("1st09".mtime) &&
!on("1st10".mtime) &&
!on("1st11".mtime) &&
!on("1st12".mtime) &&
# Not last modified on the 1st of January for the past 12 years
!on("1stJan00".mtime) &&
!on("1stJan01".mtime) &&
!on("1stJan02".mtime) &&
!on("1stJan03".mtime) &&
!on("1stJan04".mtime) &&
!on("1stJan05".mtime) &&
!on("1stJan06".mtime) &&
!on("1stJan07".mtime) &&
!on("1stJan08".mtime) &&
!on("1stJan09".mtime) &&
!on("1stJan10".mtime) &&
!on("1stJan11".mtime) &&
!on("1stJan12".mtime)
'
# Clean up the timestamped reference files
rm 1st[01][0-9] 1stJan[01][0-9]
它被硬编码到单个备份目录,但在命令行上使用一个目录很容易。不过,这样做可能很危险。出去要小心。
同样的事情可以在寻找方式大致相同,只是语法不同,语法更多,带时间戳的参考文件数量是两倍。