"find -mtime +5 | xargs rm -rf" 销毁整个目录,即使存在超过 5 天的文件

"find -mtime +5 | xargs rm -rf" destroying whole directories, even when files newer than 5 days exist

我有一系列这样的文件夹、子文件夹和文件:

year_folder
    month1_folder
       day1_folder
           filea, fileb
       day2_folder
           filea
    month2_folder

我想删除超过 X 天的文件夹和文件。 我试过了

find /c/Documents/year_folder -mtime +5 | xargs rm -rf

此命令行在我的测试文件夹(在我的计算机本地)上完美运行。 但是当我 运行 synology 上的脚本时,它以某种方式删除了整个 year_folder.

不幸的是,我不知道如何在 synology 服务器上测试我的脚本以了解我做错了什么。

使用 GNU 扩展

把它分成两部分:

  • 删除超过五天的文件(仅限!)

    # for GNU find; see below for POSIX
    find "$root" -type f -mtime +5 -delete
    
  • 删除空目录

    # for GNU find; see below for POSIX
    find "$root" -depth -type d -empty -delete
    

当您使用 rm -rf 时,如果目录本身在五天内没有更新,您将删除整个目录。但是,如果您创建或修改 a/b/c,那不会更新 a 的修改时间(或者,在不需要更新目录本身的修改的情况下,甚至a/b) -- 因此,当你递归应用它时,你的 "modification time older than five days" 规则是破坏性的。

以上唯一需要注意的是,它可能不会在运行处删除多层空目录——也就是说,如果a/b/c是空的,而a/bc 以外为空,则在第一个 运行 上只能删除 c,并且在删除 a/b 之前可能需要另一次调用。


支持基线POSIX

POSIX find 不支持 -delete。因此,第一个命令变为:

find "$root" -type f -mtime +5 -exec rm -rf -- {} +

同样不支持-empty。因为 rmdir 在传递非空目录时会失败,但是,让那些引用非空目录的实例失败很容易:

find "$root" -depth -type d -exec rmdir -- {} +

如果您不愿意这样做,事情就会变得更加棘手。使用 shell 来测试每个目录是否为空的实现可能如下所示:

find "$root" -depth -type d -exec sh -c '
  rmdir_if_empty() {
    dir=
    set -- "$dir"/*                           # replace argument list w/ glob result
    [ "$#" -gt 1 ] && return                  # globbed to multiple results: nonempty
    { [ -e "" ] || [ -L "" ]; } && return # globbed to one result that exists: nonempty
    rmdir -- "$dir"                           # neither of the above: empty, so delete.
  }
  for arg; do
    rmdir_if_empty "$arg"
  done
' _ {} +