如何查找按扩展名分组的总文件大小

如何查找按扩展名分组的总文件大小

我在与其他同事共享的集群上工作。硬盘空间有限(有时已满),所以我偶尔会清理我的部分。我想快速完成此操作,因此到目前为止,我通过列出 3 个月以上、大小超过 100 MB 的文件列表来实现此目的,然后查看是否仍然需要它们。

但现在我认为可能有一个文件夹包含超过 1000 个较小的文件,我错过了,所以我想找到一种简单的方法来查看是否是这种情况。从我生成数据的方式来看,这将有助于获取每个扩展的总大小列表。在这个问题的上下文中,“扩展名”是文件名最后一个点后面的所有内容。

假设我有多个包含多个文件的文件夹:

folder1/file1.bmp   40 kiB
folder1/file2.jpg   20 kiB
folder2/file3.bmp   30 kiB
folder2/file4.jpg    8 kiB

是否可以列出每个文件扩展名的总文件大小,如下所示:

bmp 70 kiB
jpg 28 kiB

我不关心没有扩展名的文件,因此可以忽略它们或将其放入一类中。

我已经浏览了lsdu和的手册页find,但我不知道什么是适合这项工作的工具......

答案1

在 GNU 系统上:

LC_ALL=C find . -name '?*.*' -type f -printf '%b.%f\0' |
  LC_ALL=C gawk -F . -v RS='\0' '
    {s[$NF] += $1; n[$NF]++}
    END {
      PROCINFO["sorted_in"] = "@val_num_asc"
      for (e in s) printf "%15d %4d %s\n", s[e]*512, n[e], e
    }'

或者与 相同perl,避免-printfGNU 扩展find(仍然使用 GNU 扩展 ,-print0但现在这个扩展得到了更广泛的支持):

LC_ALL=C find . -name '?*.*' -type f -print0 |
  perl -0ne '
    if (@s = lstat$_){
      ($ext = $_) =~ s/.*\.//s;
      $s{$ext} += $s[12];
      $n{$ext}++;
    }
    END {
      for (sort{$s{$a} <=> $s{$b}} keys %s) {
        printf "%15d %4d %s\n",  $s{$_}<<9, $n{$_}, $_;
      }
    }'

它给出如下输出:

          12288    1 pnm
          16384    4 gif
         204800    2 ico
        1040384   17 jpg
        2752512   83 png

如果您想要KiB, MiB... 后缀,请通过管道传输到numfmt --to=iec-i --suffix=B.

%b*512给出了磁盘使用情况,但请注意,如果文件被硬链接多次,它们将被计数多次,因此您可能会看到与报告的差异du


1 作为例外,在 HP/UX 上,lstat()/报告的块大小stat()是 1024 而不是 512。GNUfind对此进行了调整,因此它%b仍然表示 512 字节单元的数量,但是对于perl,您需要乘以 1024 。

答案2

这是另一个解决方案:

find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u | LC_ALL=C xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \; | egrep "^\.[a-zA-Z0-9]+$|total$" | uniq | paste - -

获得扩展的部分是:

find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u

接下来搜索带有扩展名的文件并将其打印在屏幕上:

LC_ALL=C xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \;

接下来我们要保留扩展名和总数:

egrep "^\.[a-zA-Z0-9]+$|total$" | uniq

并将其保持在同一行:

paste - -

答案3

不如斯蒂芬的解决方案那么好,但你可以尝试

find . -type f -name "*.png" -print0 | xargs -0r du -ch | tail -n1

您必须为每种类型的文件运行此命令。

答案4

由于我还没有足够的声誉点来写评论,我将在这里扩展 Stéphane Chazelas 的答案。要在列表中包含没有扩展名的文件(例如可执行文件),可以使用以下命令行:

find . -name '*' -type f -printf '%b.%f\0' | awk -F . -v RS='\0' '{if (NF==2) $(NF+1)=" "; s[$NF] += $1; n[$NF]++} END {for (e in s) printf "%15d %6d  %s\n", s[e]*512, n[e], e}' | sort -rn | numfmt --to=iec-i --suffix=B

相关内容