bash复杂的发现

时间:2015-12-03 14:27:26

标签: bash find

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

find $jenkins_jobs -type d -name builds -exec find {} -type d -mtime +30 \; >> $filesToBeDelete
cat $filesToBeDelete | xargs rm -rf

但后来添加了一些条件:仅当我们有超过30个构建并清理最旧的构建时才删除。所以在结果中我们应该保留30个最新的构建并删除其余部分。

此外,我发现我可以在查找中使用if语句:

if [ $(find bla-bla | wc -l) -gt 30 ]; then
...
fi

但是我在闲逛如何删除这些文件。

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

3 个答案:

答案 0 :(得分:2)

非常hacky但对于奇怪的文件名应该非常强大

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之前显示正确的文件。

所以它的作用是传递空终止字符串,因此保留了文件名。

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

答案 1 :(得分:0)

如果您的stat足够接近我的(cygwin / bash),这是列出dirs的相对安全答案:

now=$(date +%s)
find $jenkins_jobs -type d -name builds -exec find {} -type d |
  while read f; do stat -c'%Y %n' "$f"; done |
  sort -nr |
  tail -n +31 |
  awk $now'-$1>2592000'|
  sed 's/^[0-9]* //'

这适用于%s date%Y stat提供的纪元时间(自1970年以来的秒数)。 sorttail正在删除最新的30,而awk正在删除任何30天或更新的版本。 (2592000是30天内的秒数。)最终sed只是删除了stat添加的内容,只留下了dirname。

答案 2 :(得分:-2)

这将列出所有,但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

它是这样读的:

  • 找到所有构建目录
  • 从时代开始列出时间
  • drop(sed-away)权限,用户,组atc,只留下时间和名称
  • 按时间从最新
  • 排序
  • 放弃那些时间
  • tail将显示31.条目中的所有内容(因此跳过最新的30条)