根据目录的总体大小,然后根据其中的文件数量来移动目录

根据目录的总体大小,然后根据其中的文件数量来移动目录

我正在尝试清理所有音乐文件夹(有很多) - 但我不想删除,而是想移动那些空的、或者只有几 Mb 的、或者只有几个文件的文件夹。

我设法使用以下find命令来移动所有空目录:

find . -empty -type d -exec mv {} /share/Container/beetsV2/music/my_empty_folders \;

...但我似乎无法弄清楚如何根据大小查找目录。我认为以下内容会起作用,但事实并非如此;它的回报似乎比预期的要多。

find . -size -5M -type d -exec mv {} /share/Container/beetsV2/music/my_folders_under_5Mb \;

当涉及到查找仅包含几个文件的目录时,我似乎找不到单个命令行来执行上述操作。存在吗?

答案1

man find

-size n[cwbkMG] 文件使用少于、多于或恰好 n 个单位的空间,向上舍入。

此开关与目录无关磁盘使用情况


解决方法是使用bash处理find输出中的所有目录,获取每个目录的大小,mv如果大小小于 N MiB,则获取每个目录的大小:

move_dirs_smaller_than() {
    export MAX=$(($1*1024)) # $1 is in MiB
    export path=$2          # $2 /path must be outside of .
    find . -mindepth 1 -type d -exec bash -c '
        read size _ < <(du -sk "$1")
        ((size < MAX)) && echo mv -- "$1" "$path"
    ' bash {} \; -prune
}

echo当输出看起来足够好时删除语句。

5MiB 的函数用法:

/path应该不是在当前目录中(或使用find ! ./dir):

move_dirs_smaller_than 5 /path

查看find有关 的手册页-prune-mindepth-maxdepth根据您的需要。

答案2

GNU 实现du可以为您提供以下报告:

  • 累积磁盘使用量(默认)
  • 累积大小与--apparent-size
  • 文件(任何类型)的累积数量--inode

对于目录及其内容(不幸的是,它不能在一份报告中包含所有三个内容)。

您还可以告诉它不要使用 -l/删除重复的硬链接--count-links

它是少数可以可靠地对输出进行后处理的产品之一,因为它有一个-0/--null选项来输出 NUL 分隔的记录。

因此,如果您使用的是 GNU 系统,您可以这样做:

xargs -r0a <(
  du --inode --null --count-links | # count inodes
    tac -s '' | # reverse the output so parents are shown before children
    perl -0lnse '
      if (
        m{^(\d+)\t(.*)}s &&
        $1 < $max &&
        rindex($2, "$last_moved/", 0) < 0 # not a subdirectory of the last moved
      ) {
        print($last_moved = $2);
      }' -- -max=10
  ) echo mv -it /path/to/destination --

这将移动包含(递归地)少于 10 个文件的目录(任何类型,包括目录,也包括目录本身)。

替换--inode--apparent-size --block-size=1(或-b简称)以考虑累积大小而不是文件数量。与磁盘使用情况相同--apparent-size(您需要-max相应更新)。

如果对结果满意,请删除echo以实际执行。

所有-r, -0, -a, --inode, --apparent-size, -l, --count-links, tac, -b, --block-size,-t都是非标准 GNU 扩展,其中很少有已添加到这些标准实用程序的其他实现中,因此不要指望它们可以在 GNU 系统之外工作,除非您已经安装了 GNUcoreutils并且findutils那里。既然您已经使用了 linux 标签,那么您很有可能使用的是 GNU 系统。

要考虑文件数量和累积大小,您可以使用 GNU find,它有一个-printf谓词可以报告文件类型和大小并手动求和:

xargs -r0a <(
  find . -depth -printf '%y %s %p\0' | perl -0lsne '
    if (m{^(\S+) (\d+) ((.*)/.*)}s) {
      my ($type, $size, $file, $parent) = ($1, $2, $3, $4);
      $count{$parent} += ++$count{$file};
      $size{$parent} += $size{$file} += $size;
      unshift @dirs, $file if $type eq "d";
    }
    END {
      for $dir (@dirs) {
        if (
          $size{$dir} < $max_size &&
          $count{$dir} < $max_count &&
          rindex($dir, "$last_moved/", 0) < 0
        ) {
          print $last_moved = $dir;
        }
      }
    }' -- -max_count=10 -max_size="$(( 5 * 1024 * 1024 ))"
  ) echo mv -it /path/to/destination --

对于磁盘使用情况而不是表观大小,请将其替换%s%b您必须乘以 512(替换$2$2 * 512上面)以获得以字节为单位的磁盘使用情况。

相关内容