删除除每月最后一个文件之外的所有文件

删除除每月最后一个文件之外的所有文件

考虑一个包含 MySQL 备份文件的目录,其中时间戳作为文件名的一部分:

-rw-rw-r-- 1 ubuntu ubuntu 35856184 Nov 16 16:00 db_2013-11-16_1600.sql
-rw-rw-r-- 1 ubuntu ubuntu 35856915 Nov 16 17:00 db_2013-11-16_1700.sql
-rw-rw-r-- 1 ubuntu ubuntu 35857565 Nov 16 18:00 db_2013-11-16_1800.sql
-rw-rw-r-- 1 ubuntu ubuntu 35858254 Nov 16 19:00 db_2013-11-16_1900.sql
-rw-rw-r-- 1 ubuntu ubuntu 35860276 Nov 16 20:00 db_2013-11-16_2000.sql
-rw-rw-r-- 1 ubuntu ubuntu 35861583 Nov 16 21:00 db_2013-11-16_2100.sql
-rw-rw-r-- 1 ubuntu ubuntu 35863630 Nov 16 22:00 db_2013-11-16_2200.sql
-rw-rw-r-- 1 ubuntu ubuntu 35864868 Nov 16 23:00 db_2013-11-16_2300.sql
-rw-rw-r-- 1 ubuntu ubuntu 35866095 Nov 17 00:00 db_2013-11-17_0000.sql
-rw-rw-r-- 1 ubuntu ubuntu 35887731 Nov 17 01:00 db_2013-11-17_0100.sql
-rw-rw-r-- 1 ubuntu ubuntu 35888871 Nov 17 02:00 db_2013-11-17_0200.sql
-rw-rw-r-- 1 ubuntu ubuntu 35888871 Nov 17 03:00 db_2013-11-17_0300.sql
-rw-rw-r-- 1 ubuntu ubuntu 35889319 Nov 17 04:00 db_2013-11-17_0400.sql

这些实际上从 2012 年 9 月就开始了!我需要删除除每月最后一个备份之外的所有备份。也就是说,应该保留这些文件:

db_2012-09-30_2300.sql
db_2012-10-31_2300.sql
db_2012-11-30_2300.sql
db_2012-12-31_2300.sql
db_2013-01-31_2300.sql
db_2013-02-28_2300.sql
db_2013-03-31_2300.sql
db_2013-04-30_2300.sql
db_2013-05-30_2300.sql
db_2013-06-30_2300.sql
db_2013-07-31_2300.sql
db_2013-08-31_2300.sql
db_2013-09-30_2300.sql
db_2013-10-31_2300.sql
db_2013-11-20_0700.sql # Because this month has not finished yet!

我可以编写一个 Bash/Python 脚本来创建每个月的列表,从列表中删除最后一项,然后一一删除剩余的文件。或者,脚本可以将每个月的最后一个文件移动到临时目录,删除所有内容,然后将文件放回去。

然而我想知道是否有某种方法可以简单地告诉rm(或使用findandawk和rm sort)忽略本月的最后一个文件。有这样的魔法吗?

我确实认识到,如果我能够储蓄,生活会更容易第一个文件从每个月开始(与保存数据仅相差 1 小时)最后的每月的文件),但这对于组织中的其他人来说是不可接受的,因为他们看不到这本质上提供了相同的保护。

答案1

如果文件 zz 包含文件名列表,则此方法有效,因此只需替换 cat zz 即可。

cat zz | grep -vF -f <(cat zz|sort -r|uniq -w11)

例如 echo *.sql | grep -vF -f <( echo *.sql | sort -r | uniq -w11 ) | xargs rm

事实上,如果文件名中有空格,并且文件名长度非常脆弱,它将无法工作。

答案2

在脚本中进行快速丑陋的暴力尝试(可以在一行中完成,但需要两个 for 循环,因此在一行中有点丑陋)

#! /bin/bash

for year in {2012..2013}
do
   for month in {01..12}
   do
      ls db_"$year"-"$month"*.sql 2>/dev/null | sort -r | tail -n +2 | xargs rm -f
   done
done

当然,这假设文件名中没有特殊字符/空格,这似乎就是您的情况。

答案3

使用理查德的想法删除除最后一个月之外的所有内容:

rm -f `ls *.sql | sort | uniq w11 -D -u`

要查看将删除的内容:

ls *.sql | sort | uniq w11 -D -u

答案4

我会为此使用 find ,

类似的东西find "path" -type f -mtime +30 -exec rm {} \;

-mtime +30 表示 30 天,但可以轻松更改以满足您的需求。

编辑 或者,您可以使用上面的脚本设置一个 cron 任务,而不是使用 mv 将其移动到方便的位置。

相关内容