假设有一个映像存储目录./photos/john_doe,其中有多个子目录,其中驻留了许多特定文件(例如*.jpg)。我如何计算john_doe分支下的那些文件的摘要大小?

我尝试了du -hs ./photos/john_doe/*/*.jpg,但这仅显示单个文件。另外,它只跟踪john_doe目录的第一个嵌套级别,例如john_doe/june/,但跳过john_doe/june/outrageous/。 />

#1 楼

find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$


如果由于文件列表很长而需要多次调用du,则将报告多个总计,并且需要对其进行汇总。

评论


查找-iname'文件*'-exec du -cb {} + | grep total $ |切-f1 |粘贴-sd +-| bc#字节总和

– MichalČizmazia
2015年7月15日13:55



如果您的系统使用其他语言运行,则需要将total $更改为波兰语中的razem $之类的其他单词。

– Zbyszek
15年7月26日在12:49

您可以像这样在总的grep中添加LC_ALL = POSIX作为总前缀:LC_ALL = POSIX find ./photos/john_doe -type f -name'* .jpg'-exec du -ch {} + | grep总计$

– Sven
16年6月27日在5:48

如果不使用-name,则将grep更改为grep -P“ \ ttotal $”,否则它将捕获所有以“ total”结尾的文件。

– thdoan
17 Mar 30 '17在7:43

@MichalČizmazia某些外壳程序(例如Windows的Git Bash)不附带bc,因此这是一种更可移植的解决方案:find -name'* .jpg'-type f -exec du -bc {} grep total $ |切-f1 | awk'{总计+ = $ 1}; END {打印总计}'

– thdoan
17 Mar 30 '17 at 7:55

#2 楼

du -ch public_html/images/*.jpg | grep total
20M total


为我提供了该目录中.jpg文件的全部使用情况。 >
您会发现du命令示例很有用(它还包括find

评论


这不会遍历基础目录吗?

–mbaitoff
2012年6月26日下午5:48

这比接受的解决方案更容易键入,但是只有一半正确,它不会在子目录中包含图像。很高兴知道所有文件是否都在一个目录中。

– gbmhunter
19年8月29日在19:56

@gbmhunter我认为,如果将-R参数添加到-ch,您还将获得子目录,因为它以递归方式遍历目录树。我目前不在电脑上尝试进行确认。

–莱文
19年8月29日在23:04

我在man7.org/linux/man-pages/man1/du.1.html上没有看到-R选项。而且我不认为在这种情况下递归选项会有所帮助,因为外壳程序会在将参数传递给du之前进行glob扩展。

– gbmhunter
19年8月30日在21:56

要在子目录中获取图像,您不能使用** / *。jpg吗?

–凯尔·巴伦(Kyle Barron)
19年11月26日在17:30

#3 楼

首先,您需要做两件事:-cdu选项,告诉它产生总计;
**(激活说明)或find(示例),或者遍历子目录。

du -ch -- **/*.jpg | tail -n 1


评论


很好的答复。比使用find更简单(只要*或**匹配目录结构)

–安德烈·德·米兰达(Andre de Miranda)
16年4月21日在5:13

它还可以处理很长的文件列表,而使用find可能会返回错误的结果。

–埃里克·富尼(Eric Fournie)
16-10-19在8:50

bash括号扩展也允许测量多组通配符。 du -ch-./{dir1,dir2}/*.jpg或du -ch-./{prefix1*,prefix2*}.jpg

– J.Money
19年7月23日在22:24

@EricFournie但是,当处理大约300k文本文件时,出现参数列表过长的错误。

– xtluo
19年8月1日在7:43

可以使用getconf ARG_MAX检查命令的最大参数数量(在这种情况下,是通配符扩展返回的文件名)。如果有更多文件,则需要使用for循环逐个或逐批处理文件。

–埃里克·富尼(Eric Fournie)
19年8月1日在8:09

#4 楼

最终的答案是:

{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc


甚至更快的版本,不受RAM的限制,但这需要具有bignum支持的GNU AWK:

此版本具有以下功能:


find的所有功能都可以指定要查找的文件
支持数百万个文件
/>

此处的其他答案受参数列表的最大长度限制


仅生成3个具有最小管道吞吐量的简单进程


这里有很多答案,它们产生C + N个进程,其中C是一个常数,N是文件数。 >

此版本不执行任何grepping或正则表达式
find进行文件名的简单通配符匹配


可选地格式化和转换为人类可读的形式(例如5.5K176.7M,...)

评论


我喜欢这个答案的简单性,尽管它仅对我有用,在我在开括号之后和闭括号之前引入空格时才有用。我确实想知道它是否真的会支持'infiinte'数量的文件:)

– andyb
17年2月7日在0:29



@andyb感谢您的反馈,在BASH中确实需要花括号周围的空格,我使用的是ZSH,所以我没有注意到。随着bc的内存使用量随着数字的流入而缓慢增长,文件的数量受到系统上可用RAM的限制。

–rindeal
17年2月7日在17:31



#5 楼

到现在为止给出的答案都没有考虑到从find到du传递的文件列表可能太长,以至于find会自动将列表拆分成多个块,从而导致total的多次出现。 grep total(语言环境!)并手动汇总,或使用其他命令。 AFAIK只有两种方法可以找到由find找到的所有文件的总和(以千字节为单位): * .JPG,*。Jpg ...)并输出(以null终止)。 find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=} END {print sum}'
-r:即使未传递任何参数,Xargs也会调用该命令,-r可以防止。 -0表示以null终止的字符串(不以换行符终止)。 find . -type f -iname '*.jpg' -print0:总结上一条命令输出的文件大小

作为参考,另一种方式是xargs -r0 du -a

评论


附加提示:在具有23428个文件(22323是图像)的HDD上,第一种方法运行1秒,而第二种方法运行3.8秒。

– Jan
2014年8月5日在10:12

请注意,两者均假定为GNU系统。第一个假设文件名不包含换行符。

–StéphaneChazelas
2014年8月6日13:06

我敢打赌du --file0-from花了更长的时间,因为您先运行了它(缓存效果)。

–StéphaneChazelas
2014年8月6日13:07

使用xargs时,可能会运行多个du -a,因此如果存在硬链接,则可能会有差异。

–StéphaneChazelas
2014年8月6日13:09

#6 楼

如果文件列表太大而不能传递给GNU系统上的du -c单个调用,则可以执行以下操作:

find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
  sort -u | cut -f1 | paste -sd+ - | bc


(size以512字节块的数量表示)。像du一样,它只尝试计算一次硬链接。如果您不关心硬链接,则可以将其简化为:

(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc


如果要大小而不是磁盘使用率,请将%b替换为%s。大小将以字节表示。

评论


-bash:bc:找不到命令Centos-Linux 2.6.32-431.el6.x86_64

– yeya
18年1月10日在11:32

@yeya,听起来您的CentOS部署已损坏。 bc是非可选的POSIX命令。

–StéphaneChazelas
18年1月10日在11:35

#7 楼

到目前为止提到的解决方案效率低下(exec成本很高),并且如果文件列表很长或者它们不能在Mac OS X上运行,则需要进行额外的手动工作才能总结。以下解决方案非常快,可以在任何系统上使用,并且产生以GB为单位的总答案(如果要以MB单位显示,则删除/ 1024):
find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'

评论


-iname和-ls都不是标准/便携式的,因此它也不能在任何系统上运行。如果有包含换行符的文件名或符号链接目标,它也将无法正常工作。

–StéphaneChazelas
16年6月22日在8:28

还要注意,它给出的是文件大小的总和,而不是磁盘的使用情况。对于符号链接,它给出符号链接的大小,而不是它们指向的文件。

–StéphaneChazelas
16年6月22日在8:31

#8 楼

改善SHW的绝佳答案,使其可以在任何语言环境下使用,就像Zbyszek在其评论中已经指出的那样:

LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$


#9 楼

du自然会遍历目录层次结构,而awk可以执行过滤,因此这样的操作就足够了:

评论


这更加昂贵,因为它需要对不符合搜索模式的文件进行统计调用。

–法律29
16年7月1日在9:03

仅此解决方案适用于我的mac。

–Matthias M
17年5月26日在10:04



它假定文件名不包含换行符,并且不存在名称以.jpg结尾的目录。

–StéphaneChazelas
20 Jan 22 '14:43

#10 楼

这对我有用。

find -type f -iname *.jpg -print0 | du -ch --files0-from=- | grep total$


评论


这或多或少是另一个答案的副本(最后的琐碎grep除外)。

– Kusalananda♦
20 Mar 29 '20 at 16:50

#11 楼

另一个是

ls -al <directory> | awk '{t+=}END{print t}}'


假设您在单个目录中查找。如果要查看当前目录及其下的目录

ls -Ral <directory> | awk '{t+=}END{print t}}'


评论


(1)最大的问题:这看起来所有东西,但是问题特别是关于将搜索限制到文件的子集;例如* .jpg。 (并且问题明确指出,OP希望进行递归目录搜索。)(2)这将不仅适用于名称不匹配的文件(例如* .gif,*。png等),而且非文件;例如目录和符号链接。 (3)如果任何文件名包含换行符,这可能会产生错误的结果。 (4)很像(较差的)答案,这多次计算硬链接。 …(续)

–斯科特
20 Mar 9 '20 at 17:37

(续)…提示:当问题已经存在将近8年并且有9个答案时,很可能已经给出了所有好的答案,因此您应该认真考虑一下您是否真的有一些新的更好的东西做出贡献。

–斯科特
20 Mar 9 '20 at 17:37

#12 楼

使用stat而不是du的其他替代方法
stat -L -c %s ** | awk '{s+=} END {printf "%.0f\n", s}'


有关使用**
的信息,请参见Gilles的答案

#13 楼

这是我需要做的几个答案和注释的混搭。 >
find . \( -iname "*.jpg" -o -iname "*.png" \) -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += }; END { print total }'| numfmt --to=iec用于区分大小写

find和括号以查找多个模式

-iname将获得文件的大小,如果存在,有时会在多个调用中获得有许多文件

-o将仅获得du -bc给定的grep total


total将仅获取实际整数值

du会将它们全部求和

cut -f1会将其转换为人类可读的格式


评论


如果当前语言环境显示的总计标签带有不同于“总计”的标签,则它将无法正常工作

–mbaitoff
20-05-26在15:37