bash上的复杂发现

bash上的复杂发现,bash,find,Bash,Find,我有以下任务:删除超过30天的旧“构建”。这个解决方案非常有效: find $jenkins_jobs -type d -name builds -exec find {} -type d -mtime +30 \; >> $filesToBeDelete cat $filesToBeDelete | xargs rm -rf 但后来增加了一些条件:只有在我们有30多个版本时才删除,并清理最旧的版本。所以在结果中,我们应该保留30个最新版本,并删除其余版本 我还发现我可以在find

我有以下任务:删除超过30天的旧“构建”。这个解决方案非常有效:

find $jenkins_jobs -type d -name builds -exec find {} -type d -mtime +30 \; >> $filesToBeDelete
cat $filesToBeDelete | xargs rm -rf
但后来增加了一些条件:只有在我们有30多个版本时才删除,并清理最旧的版本。所以在结果中,我们应该保留30个最新版本,并删除其余版本

我还发现我可以在find中使用if语句,如下所示:

if [ $(find bla-bla | wc -l) -gt 30 ]; then
...
fi
但是我在想我怎样才能删除这些文件


清楚吗?例如,我们在“build”文件夹中有100个版本,所有版本都超过30天。所以我想保留30个新版本,删除另外70个

这将列出除30个最新董事会以外的所有董事会

find -type d -name builds -exec ls -d -l --time-style="+%s" {} \;|sed "s#[^ ]\+ \w\+ \w\+ \w\+ \w\+ ##"|sort -r |sed "s#[^ ]\+ ##"|tail -n +31
确定要删除它们后,可以使用| xargs rm-rf

它是这样写的:

  • 查找所有构建目录
  • 列出它们与时代的时间
  • 删除(sed-away)权限、用户、组atc,只留下时间和名称
  • 从最新开始按时间排序
  • 放弃那些时间
  • 尾巴将显示从31开始的一切。条目(因此跳过30)

这将列出除30个最新董事会以外的所有董事会

find -type d -name builds -exec ls -d -l --time-style="+%s" {} \;|sed "s#[^ ]\+ \w\+ \w\+ \w\+ \w\+ ##"|sort -r |sed "s#[^ ]\+ ##"|tail -n +31
确定要删除它们后,可以使用| xargs rm-rf

它是这样写的:

  • 查找所有构建目录
  • 列出它们与时代的时间
  • 删除(sed-away)权限、用户、组atc,只留下时间和名称
  • 从最新开始按时间排序
  • 放弃那些时间
  • 尾巴将显示从31开始的一切。条目(因此跳过30)

非常粗糙,但对于奇怪的文件名应该非常健壮

find -type d -name "builds" -mtime +30 -printf "%T@ %p\0" |\
awk -vRS="\0" -vORS="\0" '{match($0,/([^ ]* )(.*)/,a);b[a[2]]=a[1];c[a[1]]=a[2]}END{x=asort(b);for(i=x-30;i>0;i--)print c[b[i]]}' |\
xargs -0 -I{} rm -r {}
我用echo进行了测试,它似乎可以工作,但在使用rm-r之前,我会确保它显示了正确的文件

因此,它所做的是传递以null结尾的字符串,以便保留文件名


主要的限制是,如果在同一秒内创建了两个文件,那么它将丢失一个文件,因为它使用了关联数组。

非常粗糙,但对于奇怪的文件名应该非常健壮

find -type d -name "builds" -mtime +30 -printf "%T@ %p\0" |\
awk -vRS="\0" -vORS="\0" '{match($0,/([^ ]* )(.*)/,a);b[a[2]]=a[1];c[a[1]]=a[2]}END{x=asort(b);for(i=x-30;i>0;i--)print c[b[i]]}' |\
xargs -0 -I{} rm -r {}
我用echo进行了测试,它似乎可以工作,但在使用rm-r之前,我会确保它显示了正确的文件

因此,它所做的是传递以null结尾的字符串,以便保留文件名

主要的限制是,如果在同一秒钟内创建了两个文件,那么它将丢失一个文件,因为它使用关联数组。

如果您的
统计数据与我的数据足够接近(cygwin/bash),这里有一个相对安全的答案来列出目录:

这是根据日期的
%s
和统计的
%Y
提供的历元时间(自1970年起的秒数)工作的。
sort
tail
正在删除最新的30天,而
awk
正在删除任何30天的旧的或更新的。(2592000是30天内的秒数。)最后的
sed
只是删除了
stat
添加的内容,只留下目录名。

如果你的
stat
与我的目录足够接近(cygwin/bash),这里有一个相对安全的答案来列出目录:


这是根据日期的
%s
和统计的
%Y
提供的历元时间(自1970年起的秒数)工作的。
sort
tail
正在删除最新的30天,而
awk
正在删除任何30天的旧的或更新的。(2592000是30天内的秒数。)最后的
sed
只是删除了
stat
添加的内容,只留下目录名。

是的,这很清楚,但我想我有坏消息要告诉你。我认为
find
不能胜任这项任务
find
以每个文件为基础进行操作(除了可能用多个文件名填充命令行之外),并且不能比较不同的点击,除非
find
有我从未听说过的更高级的功能。我认为您需要手动对时间戳进行排序(除非您求助于一些不太安全的黑客解决方案),然后执行您的逻辑,这在Python或Perl中要容易得多;您应该使用
-exec rm-rf'{}+
find blah blah-print0 | xargs-0
(如果您有一个更原始的
find
),因为默认情况下不应解析
find
输出(例如,尝试使用换行符的文件名)@4ae1e1我认为它工作得很好,因为它们有健全的文件名,所以没有理由使用它们。事实上,我应该使用bash,因为它只是大脚本的一小部分。是否可以在多个步骤中执行?我的意思是,首先,如果有超过30个版本,那么以后再选择较旧的文件。。。etc@123我听说有人有健全的文件名和愉快地使用shell脚本,直到有一天他们有一些坏程序转储随机垃圾(随机名称)。是的,这很清楚,但我想我有坏消息要告诉你。我认为
find
不能胜任这项任务
find
以每个文件为基础进行操作(除了可能用多个文件名填充命令行之外),并且不能比较不同的点击,除非
find
有我从未听说过的更高级的功能。我认为您需要手动对时间戳进行排序(除非您求助于一些不太安全的黑客解决方案),然后执行您的逻辑,这在Python或Perl中要容易得多;您应该使用
-exec rm-rf'{}+
find blah blah-print0 | xargs-0
(如果您有一个更原始的
find
),因为默认情况下不应解析
find
输出(例如,尝试使用换行符的文件名)@4ae1e1我认为它工作得很好,因为它们有健全的文件名,所以没有理由使用它们。事实上,我应该使用bash,因为它只是大脚本的一小部分。是否可以在多个步骤中执行?我的意思是,首先,如果有超过30个版本,那么以后再选择较旧的文件。。。etc@123我听说有人有理智的f