Linux 小知识:ls -l 命令的输出中目录的大小是什么含义?


ls -l 或者 ll 命令是我们查看某个目录下面文件经常会执行的一个命令。典型输出如下:
ls -ltotal 12drwxr-xr-x. 2 root root 21 Mar 9 2022 aaa-rw-r--r-- 1 root root 485 Sep 7 2022 clean.shdrwxr-xr-x 7 root root 4096 Mar 25 14:11 bbb
输出说明:
文件类型和权限(File type and permissions):第一列表示文件类型和权限。以 d 开头表示是目录,以 - 开头表示是文件。接着是九个字符,分成三组,每组三个字符表示文件所有者、所属组和其他用户的权限。其中,r 表示读权限,w 表示写权限,x 表示执行权限,- 表示没有该权限。
链接数(Number of links):第二列表示文件或目录的硬链接数量。对于文件,链接数指的是指向该文件的硬链接数量。对于目录,链接数至少为2,其中一个链接是指向该目录本身的链接,另一个链接是指向该目录的父目录的链接。
所有者(Owner):第三列表示文件或目录的所有者。
所属组(Group):第四列表示文件或目录所属的用户组。
文件大小(Size):第五列表示文件的大小,以字节为单位。对于目录来说,表示目录占用的磁盘空间大小。
修改时间(Modification time):接下来是文件或目录的最后修改时间。
文件或目录名称(Name):最后一列是文件或目录的名称。
文件的大小比较好理解,但是为什么目录也有大小?而且这里的 aaa 和 bbb 还不一样?
参考 https://unix.stackexchange.com/questions/55/what-does-size-of-a-directory-mean-in-output-of-ls-l-command 我们可以知道
这是磁盘上用于存储目录元信息(即属于该目录的文件表)的空间大小。如果是 1024,则意味着磁盘上的 1024 字节被用于此目的(它总是分配完整的块)。
现代文件系统允许目录中使用长文件名和大量文件。文件名的长度和单个目录中的文件数量都会影响目录文件的大小。
我们可以使用 stat 命令来查看相关的信息:
ll aaa/total 4-rw-r--r--. 1 root root 1467 Mar 9 2022 ds.yamlstat aaa File: 'aaa' Size: 21 Blocks: 0 IO Block: 4096 directoryDevice: 802h/2050d Inode: 656400 Links: 2Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)Access: 2024-04-08 19:03:32.503911346 +0800Modify: 2022-03-09 19:29:05.726518982 +0800Change: 2024-03-22 15:52:13.323696394 +0800 Birth: -
stat bbb/ File: 'bbb/' Size: 4096 Blocks: 8 IO Block: 4096 directoryDevice: 802h/2050d Inode: 605761070 Links: 7Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)Access: 2024-04-08 19:00:01.582450675 +0800Modify: 2024-03-25 14:11:44.244953183 +0800Change: 2024-03-25 14:11:44.244953183 +0800 Birth: -
我们使用了 xfs 文件系统,可以通过如下方式获取和 xfs 文件系统相关信息:

1. 通过 xfs_info 查看
xfs_info /dev/sda2meta-data=/dev/sda2 isize=512 agcount=16, agsize=8192000 blks = sectsz=4096 attr=2, projid32bit=1 = crc=1 finobt=0 spinodes=0data = bsize=4096 blocks=131072000, imaxpct=25 = sunit=64 swidth=64 blksnaming =version 2 bsize=4096 ascii-ci=0 ftype=1log =internal bsize=4096 blocks=64000, version=2 = sectsz=4096 sunit=1 blks, lazy-count=1realtime =none extsz=4096 blocks=0, rtextents=0
superblock简称sb,我们可以看到现实的内容中包括很多当前文件系统的关键信息:
meta-data=/dev/sda2:指定文件系统的元数据存储设备。
isize=512:inode 的大小,单位为字节。
agcount=16:文件系统中的分配组(allocation group)数量。
agsize=8192000 blks:每个分配组的大小,以块为单位。
sectsz=4096:文件系统所使用的扇区大小,单位为字节。
attr=2:文件系统支持的属性(attribute)的数量。
projid32bit=1:指示文件系统是否支持32位项目标识符(project identifier)。
crc=1:表示文件系统启用了 CRC(循环冗余校验)校验。
finobt=0:指示是否启用了 inode free map B-tree。
spinodes=0:预留用于系统 inode 的数量。
data:数据区的相关信息。
bsize=4096:数据块的大小,以字节为单位。
blocks=131072000:数据区总共包含的块数。
imaxpct=25:inode 区最大百分比。
sunit=64:条带单元大小,以块为单位。
swidth=64 blks:条带宽度,以块为单位。
naming:命名相关的信息。
version 2:命名版本。
bsize=4096:块大小,以字节为单位。
ascii-ci=0:是否区分大小写。
ftype=1:文件类型,1 表示启用了文件类型。
log:日志相关的信息。
internal:日志类型。
bsize=4096:块大小,以字节为单位。
blocks=64000:日志总共包含的块数。
version=2:日志版本。
sectsz=4096:扇区大小,以字节为单位。
sunit=1:条带单元大小,以块为单位。
lazy-count=1:延迟分配的数量。
realtime:实时区相关的信息。
none:表示没有启用实时区。
extsz=4096:实时区的块大小,以字节为单位。
blocks=0:实时区总共包含的块数。
rtextents=0:实时区的扩展数量。
2. 使用 xfs_db 查看指定 inode 的信息
#注意使用期需要 umountxfs_db /dev/sdb4xfs_db> inode 1677722126xfs_db> pcore.magic = 0x494ecore.mode = 040755core.version = 3core.format = 1 (local)core.nlinkv2 = 15core.onlink = 0core.projid_lo = 0core.projid_hi = 0core.uid = 0core.gid = 0core.flushiter = 0core.atime.sec = Mon Mar 11 16:03:02 2024core.atime.nsec = 248489503core.mtime.sec = Mon Mar 11 15:54:52 2024core.mtime.nsec = 195095791core.ctime.sec = Mon Mar 11 15:54:52 2024core.ctime.nsec = 195095791core.size = 329core.nblocks = 0core.extsize = 0core.nextents = 0core.naextents = 0core.forkoff = 0core.aformat = 2 (extents)core.dmevmask = 0core.dmstate = 0core.newrtbm = 0core.prealloc = 0core.realtime = 0core.immutable = 0core.append = 0core.sync = 0core.noatime = 0core.nodump = 0core.rtinherit = 0core.projinherit = 0core.nosymlinks = 0core.extsz = 0core.extszinherit = 0core.nodefrag = 0core.filestream = 0core.gen = 3509672234next_unlinked = nullv3.crc = 0x5815bd24 (correct)v3.change_count = 25v3.lsn = 0x100001030v3.flags2 = 0v3.crtime.sec = Mon Mar 11 15:53:38 2024v3.crtime.nsec = 869587998v3.inumber = 1677722126v3.uuid = 2d206651-9b01-4e00-9800-a82b388af061u3.sfdir3.hdr.count = 19u3.sfdir3.hdr.i8count = 0u3.sfdir3.hdr.parent.i4 = 512u3.sfdir3.list[0].namelen = 8u3.sfdir3.list[0].offset = 0x60u3.sfdir3.list[0].name = "packages"u3.sfdir3.list[0].inumber.i4 = 1744831010u3.sfdir3.list[0].filetype = 2u3.sfdir3.list[1].namelen = 6u3.sfdir3.list[1].offset = 0x78u3.sfdir3.list[1].name = "images"u3.sfdir3.list[1].inumber.i4 = 1879048714u3.sfdir3.list[1].filetype = 2u3.sfdir3.list[2].namelen = 8u3.sfdir3.list[2].offset = 0x90u3.sfdir3.list[2].name = "binaries"u3.sfdir3.list[2].inumber.i4 = 2013266444u3.sfdir3.list[2].filetype = 2u3.sfdir3.list[3].namelen = 9u3.sfdir3.list[3].offset = 0xa8u3.sfdir3.list[3].name = "templates"u3.sfdir3.list[3].inumber.i4 = 603980312u3.sfdir3.list[3].filetype = 2u3.sfdir3.list[4].namelen = 6u3.sfdir3.list[4].offset = 0xc0u3.sfdir3.list[4].name = "ovsrpm"u3.sfdir3.list[4].inumber.i4 = 671089162u3.sfdir3.list[4].filetype = 2u3.sfdir3.list[5].namelen = 13u3.sfdir3.list[5].offset = 0xd8u3.sfdir3.list[5].name = "nvidia-docker"u3.sfdir3.list[5].inumber.i4 = 872415776u3.sfdir3.list[5].filetype = 2u3.sfdir3.list[6].namelen = 9u3.sfdir3.list[6].offset = 0xf8u3.sfdir3.list[6].name = "README.md"u3.sfdir3.list[6].inumber.i4 = 1677722127u3.sfdir3.list[6].filetype = 1u3.sfdir3.list[7].namelen = 11u3.sfdir3.list[7].offset = 0x110u3.sfdir3.list[7].name = "ansible.cfg"u3.sfdir3.list[7].inumber.i4 = 1677722128u3.sfdir3.list[7].filetype = 1u3.sfdir3.list[8].namelen = 11u3.sfdir3.list[8].offset = 0x128u3.sfdir3.list[8].name = "init-arm.sh"u3.sfdir3.list[8].inumber.i4 = 1677722129u3.sfdir3.list[8].filetype = 1u3.sfdir3.list[9].namelen = 11u3.sfdir3.list[9].offset = 0x140u3.sfdir3.list[9].name = "init-mix.sh"u3.sfdir3.list[9].inumber.i4 = 1677722130u3.sfdir3.list[9].filetype = 1u3.sfdir3.list[10].namelen = 7u3.sfdir3.list[10].offset = 0x158u3.sfdir3.list[10].name = "init.sh"u3.sfdir3.list[10].inumber.i4 = 1677722131u3.sfdir3.list[10].filetype = 1u3.sfdir3.list[11].namelen = 18u3.sfdir3.list[11].offset = 0x170u3.sfdir3.list[11].name = "install-ansible.sh"u3.sfdir3.list[11].inumber.i4 = 1677722132u3.sfdir3.list[11].filetype = 1u3.sfdir3.list[12].namelen = 9u3.sfdir3.list[12].offset = 0x190u3.sfdir3.list[12].name = "inventory"u3.sfdir3.list[12].inumber.i4 = 939524646u3.sfdir3.list[12].filetype = 2u3.sfdir3.list[13].namelen = 9u3.sfdir3.list[13].offset = 0x1a8u3.sfdir3.list[13].name = "playbooks"u3.sfdir3.list[13].inumber.i4 = 1074434570u3.sfdir3.list[13].filetype = 2u3.sfdir3.list[14].namelen = 8u3.sfdir3.list[14].offset = 0x1c0u3.sfdir3.list[14].name = "precheck"u3.sfdir3.list[14].inumber.i4 = 1275068958u3.sfdir3.list[14].filetype = 2u3.sfdir3.list[15].namelen = 5u3.sfdir3.list[15].offset = 0x1d8u3.sfdir3.list[15].name = "roles"u3.sfdir3.list[15].inumber.i4 = 1342177870u3.sfdir3.list[15].filetype = 2u3.sfdir3.list[16].namelen = 12u3.sfdir3.list[16].offset = 0x1f0u3.sfdir3.list[16].name = "precheck"u3.sfdir3.list[16].inumber.i4 = 1744831039u3.sfdir3.list[16].filetype = 2u3.sfdir3.list[17].namelen = 4u3.sfdir3.list[17].offset = 0x208u3.sfdir3.list[17].name = "util"u3.sfdir3.list[17].inumber.i4 = 1818741264u3.sfdir3.list[17].filetype = 2u3.sfdir3.list[18].namelen = 7u3.sfdir3.list[18].offset = 0x218u3.sfdir3.list[18].name = "yumrepo"u3.sfdir3.list[18].inumber.i4 = 1946157619u3.sfdir3.list[18].filetype = 2xfs_db> quit
我们可以看到 ls 命令中的 size 取自 inode 的 core.size,至于这块的计算,需要进行源码分析。
对于 xfs 文件系统感兴趣的同学,可以参考博客:https://zorrozou.github.io/docs/xfs/XFS%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E7%BB%93%E6%9E%84.html,以及 《XFS Algorithms & Data Structures 3rd》。
到顶部