一个目录中所有文件的内容总大小

106

当我使用lsdu命令时,会显示每个文件占用的磁盘空间大小。

我需要计算所有文件和子目录中的数据总量,即打开每个文件并计算字节数。如果我不需要打开每个文件并逐一计算,则可以获得额外加分。


1
“ls” 实际上显示每个文件的字节数,而不是磁盘空间的大小。这对您的需求是否足够? - Greg Hewgill
3
请注意,du 命令不能用来回答这个问题。它显示目录在磁盘上占用的磁盘空间(文件数据加上辅助文件系统元信息的大小)。du 命令的输出甚至可能比所有文件的总大小还要小。这可能是因为文件系统可以在磁盘上存储压缩数据或使用硬链接。正确的答案基于 lsfind 命令。请参考此处 Nelsonbytepan 的答案,或者查看这个答案:https://unix.stackexchange.com/a/471061/152606。 - anton_rh
12个回答

109

如果您想要获取“表面大小”(即每个文件中的字节数),而不是磁盘上占用的大小,请使用-b--bytes选项(如果您使用带有GNU coreutils的Linux系统):

% du -sbh <directory>

3
有没有一种简便的方法以人类可读的格式显示“表观大小”?当使用 du -shb 命令(如此答案所建议的)时,-b 设置好像会覆盖 -h 设置。 - Mathias Bynens
6
将标志的顺序颠倒过来(即使用“du -sbh <dir>”命令)。对我有效。 - Luis E.
2
@MathiasBynens du -sh --apparent-size /dir/ - Jongosi
2
@Arkady 我在CentOS和Ubuntu上尝试了你的解决方案,但出现了一个小错误。你需要使用"du -sbh"命令。"-h"标志必须放在最后。 - john_science
1
谢谢,@theJollySin!现在已经修复了。 - Arkady
显示剩余2条评论

46

使用du -sb命令:

du -sb DIR

可以选择添加h选项以获得更加用户友好的输出:

du -sbh DIR

5
“-b” 似乎是在 MacOS 的“du”命令中非法的选项。 - lynxoid
3
你可以使用brew安装GNU版本:brew install coreutils,安装后可以使用命令gdu来调用。 - neu242
1
不起作用。ls -> file.gz hardlink-to-file.gzstat -c %s file.gz -> 9657212stat -c %s hardlink-to-file.gz -> 9657212du -sb -> 9661308。它绝对不是内容的总大小,而是目录在磁盘上占用的大小。 - anton_rh

26

1
这很简单并且有效!谢谢。有时候,我喜欢添加“-L”选项,这样du就会跟随符号链接。 - conradkleinespel
2
在我的OS X上可以工作。 - sam boosalis
2
这很简单但是不起作用。它打印目录在磁盘上占用的空间,而不是通过打开每个文件并计算字节数来计算出的内容的总大小。 - anton_rh

18

这只是一种替代方法:

ls -lAR | grep -v '^d' | awk '{total += $5} END {print "Total:", total}'

grep -v '^d' 将排除目录。


4
好的,还要添加-a参数以获取“隐藏文件”(任何以点号开头的文件)。 - Nicholi
仅限于特定文件类型(在本例中为PNG),以MB为单位,以提高可读性:ls -lR | grep '.png$' | awk '{total += $5} END {print "总计:", total/1024/1024, "MB"}' - MusikPolice
这是一个正确的答案。与du不同,该解决方案确实计算了所有文件中数据的总大小,就好像它们逐个打开并计算其字节数一样。但是,是的,需要添加-A参数才能计算隐藏文件的大小。 - anton_rh

13

stat的"%s"格式可以给你一个文件中实际字节数。

 find . -type f |
 xargs stat --format=%s |
 awk '{s+=$1} END {print s}'

随意使用您最喜欢的求和方法进行替换。


4
最好使用命令 "find . -type f -print0 | xargs -0 ..." ,以避免出现某些文件名(包含空格等)的问题。 - hlovdal
1
是的,说得好。如果它不在BSD 4.2中,我就记不起来用它了 :-( - Nelson
3
йңҖиҰҒеӨ„зҗҶж–Ү件еҗҚдёӯеҢ…еҗ«з©әж јзҡ„жғ…еҶөж—¶пјҢйңҖдҪҝз”Ёе‘Ҫд»Өfind -print0е’Ңxargs -0гҖӮеңЁOS Xзі»з»ҹдёӯпјҢеә”дҪҝз”Ёе‘Ҫд»Өstat -f %zжқҘиҺ·еҸ–ж–Ү件еӨ§е°ҸгҖӮ - Kornel
1
(请注意,stat 与稀疏文件一起使用,报告文件的大名义大小,而不是像“du”报告的磁盘上使用的较小块。) - Nelson
我喜欢这个......稍加修改就可以让我以兆字节为单位获取所有 .o 文件的大小。 - mheyman
1
与其他错误使用 du 实用程序的许多答案不同,这个答案是正确的。它非常类似于这里的答案:https://unix.stackexchange.com/a/471061/152606。但我会使用 ! -type d 而不是 -type f 来计算符号链接的大小(通常只有几个字节的符号链接本身的大小,而不是它指向的文件的大小)。 - anton_rh

3

如果您在嵌入式系统中使用busybox的“du”,那么您无法获得准确的字节数,只能获得Kbytes。

BusyBox v1.4.1 (2007-11-30 20:37:49 EST) multi-call binary

Usage: du [-aHLdclsxhmk] [FILE]...

Summarize disk space used for each FILE and/or directory.
Disk space is printed in units of 1024 bytes.

Options:
        -a      Show sizes of files in addition to directories
        -H      Follow symbolic links that are FILE command line args
        -L      Follow all symbolic links encountered
        -d N    Limit output to directories (and files with -a) of depth < N
        -c      Output a grand total
        -l      Count sizes many times if hard linked
        -s      Display only a total for each argument
        -x      Skip directories on different filesystems
        -h      Print sizes in human readable format (e.g., 1K 243M 2G )
        -m      Print sizes in megabytes
        -k      Print sizes in kilobytes(default)

3

对于Win32 DOS,您可以:

c:> dir /s c:\directory\you\want

倒数第二行将告诉你文件占用的字节数。

我知道这会读取所有文件和目录,但在某些情况下运行速度更快。


3
创建文件夹时,许多Linux文件系统会分配4096个字节以存储有关目录本身的一些元数据。随着目录的增长,该空间会增加4096个字节的倍数。 du命令(带有或不带-b选项)也将考虑此空间,您可以通过输入以下内容查看:
mkdir test && du -b test

如果一个目录为空,则其结果为4096字节。因此,如果您将两个大小为10000字节的文件放入该目录中,则du -sb给出的总量将为24096字节。

仔细阅读问题,这不是所要求的。提问者问道:

如果我打开每个文件并计算字节数,所有文件和子目录中的数据总和是多少字节

在上面的示例中应为20000字节,而不是24096字节。

因此,正确答案可能是Nelson答案和hlovdal建议处理包含空格的文件名的混合。

find . -type f -print0 | xargs -0 stat --format=%s | awk '{s+=$1} END {print s}'

2
以下是在Linux/Unix和Git Bash for Windows中获取文件和子目录中所有数据的总字节数的至少三种方法,按平均速度从快到慢列出。为了参考,它们在一个相当深的文件系统的根目录下执行(在Magento 2 Enterprise安装中的docroot中,包括71,158个文件和30,027个目录)。 1.
$ time find -type f -printf '%s\n' | awk '{ total += $1 }; END { print total" bytes" }'
748660546 bytes

real    0m0.221s
user    0m0.068s
sys     0m0.160s

2.

$ time echo `find -type f -print0 | xargs -0 stat --format=%s | awk '{total+=$1} END {print total}'` bytes
748660546 bytes

real    0m0.256s
user    0m0.164s
sys     0m0.196s

3.

$ time echo `find -type f -exec du -bc {} + | grep -P "\ttotal$" | cut -f1 | awk '{ total += $1 }; END { print total }'` bytes
748660546 bytes

real    0m0.553s
user    0m0.308s
sys     0m0.416s

这两种方法也可以使用,但是它们依赖于在Git Bash for Windows上不存在的命令: 1.
$ time echo `find -type f -printf "%s + " | dc -e0 -f- -ep` bytes
748660546 bytes

real    0m0.233s
user    0m0.116s
sys     0m0.176s

2.

$ time echo `find -type f -printf '%s\n' | paste -sd+ | bc` bytes
748660546 bytes

real    0m0.242s
user    0m0.104s
sys     0m0.152s


如果你只想要当前目录下的总数,那么在find命令中加入-maxdepth 1


请注意,一些建议的解决方案可能会返回不准确的结果,所以我建议使用上述的解决方案。

$ du -sbh
832M    .

$ ls -lR | grep -v '^d' | awk '{total += $5} END {print "Total:", total}'
Total: 583772525

$ find . -type f | xargs stat --format=%s | awk '{s+=$1} END {print s}'
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
4390471

$ ls -l| grep -v '^d'| awk '{total = total + $5} END {print "Total" , total}'
Total 968133

1
关于Windows的Git Bash,如果使用Cygwin,则dcbc软件包的一部分,因此需要安装bc才能获取dc请参考此处 - ruvim

1

du很方便,但是如果你只想计算一些文件的大小(例如,使用扩展名过滤器),find非常有用。此外,请注意,find本身可以打印每个文件的大小(以字节为单位)。为了计算总大小,我们可以按以下方式连接dc命令:

find . -type f -printf "%s + " | dc -e0 -f- -ep

这里的find生成了一系列dc命令,如123 + 456 + 11 +。 尽管如此,完成的程序应该像0 123 + 456 + 11 + p一样(记住后缀表示法)。

因此,为了获得完成的程序,在执行来自stdin的序列之前,我们需要在堆栈上放置0,并在执行后打印顶部数字(最后的p命令)。 我们通过dc选项实现:

  1. -e0只是-e '0'的快捷方式,将0放入堆栈中,
  2. -f-用于从stdin读取和执行命令(这里由find生成),
  3. -ep用于打印结果(-e 'p')。

要打印以MiB为单位的大小,如284.06 MiB,可以在第3点中使用-e '2 k 1024 / 1024 / n [ MiB] p'(大多数空格是可选的)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接