我在与其他同事共享的集群上工作。硬盘空间有限(有时已满),所以我偶尔会清理我的部分。我想快速完成此操作,因此到目前为止,我通过列出 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
我不关心没有扩展名的文件,因此可以忽略它们或将其放入一类中。
我已经浏览了ls
、du
和的手册页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
,避免-printf
GNU 扩展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