平时在使用 du 统计文件大小时并不太清楚这个大小是指什么。当同样的目录放在不同的文件系统上,使用 du 统计出来的大小对不上时,我彻底迷糊了。
难道相同的文件,放在不同的存储设备上,占用的空间不一样吗?
把这个问题分解一下,文件的大小是否是固定的?du 统计出来的大小包含什么?
第一个问题:文件的大小是否是固定的?
实际上文件的大小是固定的,我们一般用多少字节来描述文件的大小,使用 stat 命令可以查看文件所占用的字节数。
$ stat ./mydu.pyFile: './mydu.py'Size: 949 Blocks: 8 IO Block: 4096 regular fileDevice: 802h/2050d Inode: 93064461 Links: 1Access: (0775/-rwxrwxr-x) Uid: ( 0/ root) Gid: ( 0/ root)Access: 2022-07-14 16:44:55.884591350 +0800Modify: 2022-07-14 16:44:53.132460870 +0800Change: 2022-07-14 16:44:53.132460870 +0800Birth: -$ du -b mydu.py949 mydu.py
比如文本文件 mydu.py 大小为 949 字节。这个是可以验证,使用 python 用的 os 模块可以获取文件大小:
import osf = './mydu.py'file_size = os.path.getsize(f)
第二个问题:du 统计出来的大小包含什么?
当 du 统计单文件时,统计的就是文件的大小。当统计目录时,包含文件的大小和目录的大小。我们看例子:
$ du -ab /root/bin1573 /root/bin/mydu2.py10670144 /root/bin/lazydocker1494 /root/bin/update_loop.sh949 /root/bin/mydu.py10678256 /root/bin
其中 -b 是以字节进行显示,-a 是显示所有内容。其中这里的 root/bin 的大小 10678256 是所有文件的大小再加上目录的大小,而所有文件的大小加起来为 10674160 ,并不等 root/bin 的大小。

这是因为 du 统计的大小包含了文件的大小和目录的大小,此时并没有单独显示目录所占的大小。在 Linux 中所有的东西都是文件,我们可以这么理解,目录也是一种特殊的文件,它存储的是放在它下面的文件的信息。目录实际上也是占空间的,它的大小也可以通过 stat 命令进行查看:
$ stat root/binFile: '/root/bin'Size: 4096 Blocks: 8 IO Block: 4096 directoryDevice: 802h/2050d Inode: 93063194 Links: 2Access: (0775/drwxrwxr-x) Uid: ( 0/ root) Gid: ( 0/ root)Access: 2022-07-14 16:45:19.409708439 +0800Modify: 2022-07-14 16:44:53.132460870 +0800Change: 2022-07-14 16:44:53.132460870 +0800Birth: -
其中 root/bin 目录占了 4096 字节,如果把这个大小与所有文件的大小加上,上面 du 统计出来的大小就对上的:
10674160 + 4096 = 10678256
所以当我们在使用 du 统计大小时,实际上会算上目录的大小。如果我们需要单独统计一个目录中所有文件的大小,怎么办?可以自己写个程序进行统计:
程序执行效果如下:
$ python3 mydu2.py /root/binsummary=======files : 4bytes : 10674160Bkilobytes : 10423.98Kmegabytes : 10.18M
当指定目录时,会统计指定目录的文件数量,以及总文件大小,分别以字节、KB、MB进行显示。
代码如下:
#!pyhton3import osimport syssum = 0fsum = 0def summary():global sumglobal fsumprint()print("summary")print("=" * 7)print("files : {0}".format(fsum))print("bytes : {0}B".format(sum))# comparison values are about 90.909% of kilo,mega,giga, and terabyteif sum > 1126:print("kilobytes : {0}K".format(round(sum/float(1024),2)))if sum > 1153433:print("megabytes : {0}M".format(round(sum/float(1024 ** 2),2)))if sum > 1181116006:print("gigabytes : {0}G".format(round(sum/float(1024 ** 3),2)))if sum > 1209462790144:print("terabytes : {0}G".format(round(sum/float(1024 ** 4),2)))if sum > 1238489897107456:print("petabytes : {0}P".format(round(sum/float(1024 ** 5),2)))def get_filesize(filePath):fbyte = os.path.getsize(filePath)return fbytedef walkFile(file):global sumglobal sum_dglobal fsumglobal dsumfor root, dirs, files in os.walk(file):# root 表示当前正在访问的文件夹路径# dirs 表示该文件夹下的子目录名list# files 表示该文件夹下的文件list# 遍历文件for f in files:fname = os.path.join(root, f)fsize = get_filesize(fname)fsum = fsum + 1sum = sum + fsizewalkFile(sys.argv[1])summary()
在使用 du 进行统计时,有可能会出现不同文件系统统计出来的结果不一致。此时没法通过 du 的结果来确定实际文件的数据量。此时可以只统计文件大小而不统计目录大小,因为文件的大小是固定的。
全文完。
如果转发本文,文末务必注明:“转自微信公众号:生有可恋”。




