![文件系统技术内幕:大数据时代海量数据存储之道](https://wfqqreader-1252317822.image.myqcloud.com/cover/284/43738284/b_43738284.jpg)
2.3 如何遍历目录中的文件
文件系统有一个常用的功能就是查看某个目录的文件列表。这个功能对应的命令行工具就是ls命令。而在GUI管理工具中,其实就是展示在我们面前的目录和文件列表等内容。
从本质上来说,目录与文件并没有太大的差异。我们也可以将目录理解为一个文件,其中的数据是一些此目录下的所有文件名相关的内容。关于目录内容的相关原理,会在后续章节进行详细介绍,本节不再赘述。
本节从程序员开发的角度介绍一下如何查看目录的内容,也就是遍历目录中的文件。Linux有一个专门的API来实现目录的遍历,这个API就是readdir。下面实现一个类似ls的命令,但是功能上要比ls命令弱很多,如代码2-2所示。
代码2-2 遍历目录的实现
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_39_1.jpg?sign=1738842228-K5juPEW8r66BUgsgd19r8qiUrrvS00iZ-0-c8f03ffc80af569b1fc2074c36f74f03)
这个程序的实现很简单,只是输出当前目录下的所有文件和子目录。编译上述代码后运行,可以得到如下结果。对比readdir命令的结果和ls命令的结果,可以看出没有太大的差异。差异在于我们实现的命令输出了当前目录(.)和父目录(..)。
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_39_2.jpg?sign=1738842228-VpDmEGT5jfnxOMBWsO5oYlvYGk0qQTeW-0-c65ecdfdefaded698fde15d92986df70)
图2-4 输出结果
通过阅读上述代码我们可以知道,这里目录项的内容是以结构体dirent(directory entry的缩写)存储的。我们可以看一下该结构体的定义(来自glibc2.32),如代码2-3所示。
代码2-3 目录项数据结构
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_39_3.jpg?sign=1738842228-P9vUOzniIGkbeJGuf221XLsRzCdvh4lP-0-0625829ce4126038bdc1ed9ec137a9c1)
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_40_1.jpg?sign=1738842228-PC2bfaRAVce52j8VW82U9AmhE4Fmx5eJ-0-457aeb489f20d5015bfdc9e36e075a4c)
通过观察该数据结构就会发现,这个数据结构只有inode ID和文件名称等信息与ls命令展示的相关。那么ls命令显示的文件的详细信息(如文件的创建时间、大小和权限等)又是如何获取的呢?
要想回答这个问题,就要看一下系统提供的一个API函数。这个API函数就是stat()函数,该函数的语法格式如下:
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_40_2.jpg?sign=1738842228-xnPBK690bi4INywGvyLjisrxUJlzkPrt-0-8863487b06a7c1cdc5b1dd11152f27c8)
从stat()函数的语法格式可以看出,该函数最主要的功能是返回一个stat类型的结构体。该结构体的定义如代码2-4所示(来自glibc 2.32)。从该结构体的定义我们可以看出,这里面包含文件非常详细的信息。通过这些信息,我们完全可以实现一个完整版的ls命令。
代码2-4 文件属性数据结构
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_40_3.jpg?sign=1738842228-JRLd6V326aOMOBAboPuVwtFlVBOtns8l-0-bfc6a1ab119721fdc44d37dadb488b75)
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_41_1.jpg?sign=1738842228-IifJ2m4fIev98uOjqWz5Gpd9ZokA24fY-0-6cc857925033dc3e7e35b0f6a40ff2c3)
关于如何实现一个完整版的ls命令本书不再赘述,大家可以自己思考并试着实现。如果实在不知道怎么写,则可以参考ls命令的源代码实现。