![文件系统技术内幕:大数据时代海量数据存储之道](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=1739288774-GfXQnAIMuHZnmGejqrL5aT5nWnG6vyqK-0-7710889d806ec7af24c87a5524d7dfd4)
这个程序的实现很简单,只是输出当前目录下的所有文件和子目录。编译上述代码后运行,可以得到如下结果。对比readdir命令的结果和ls命令的结果,可以看出没有太大的差异。差异在于我们实现的命令输出了当前目录(.)和父目录(..)。
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_39_2.jpg?sign=1739288774-3i5kuSZFov6j1HdQae5vqmcCCm4D1aTo-0-f6db13ca51f209bfb4b0612b36a13acc)
图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=1739288774-HRWdZngw6x1vmG0Rs5el427nTFumFf0D-0-e6f53f1a659adb92a059af5a59879e71)
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_40_1.jpg?sign=1739288774-IsDPokqom8oFI2RMvw7DZMH2CEaBzSZW-0-bbbc7e2850e2d974b7506d82138778c3)
通过观察该数据结构就会发现,这个数据结构只有inode ID和文件名称等信息与ls命令展示的相关。那么ls命令显示的文件的详细信息(如文件的创建时间、大小和权限等)又是如何获取的呢?
要想回答这个问题,就要看一下系统提供的一个API函数。这个API函数就是stat()函数,该函数的语法格式如下:
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_40_2.jpg?sign=1739288774-djGY4tEVhOvAuZiQ5Mzrwvm7fGrF2p9K-0-21f4c97ec5cd501b3190043e2290f96c)
从stat()函数的语法格式可以看出,该函数最主要的功能是返回一个stat类型的结构体。该结构体的定义如代码2-4所示(来自glibc 2.32)。从该结构体的定义我们可以看出,这里面包含文件非常详细的信息。通过这些信息,我们完全可以实现一个完整版的ls命令。
代码2-4 文件属性数据结构
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_40_3.jpg?sign=1739288774-THqEkR54KfUIEdmyYsmzJiQaNOwj6Zqw-0-cbb6e7f1f731881ffcb4dd6100430fd2)
![](https://epubservercos.yuewen.com/F77410/23020648909757306/epubprivate/OEBPS/Images/42478_41_1.jpg?sign=1739288774-jrNiYmbH1aTwJFBPCxQwSEKmqWcFxbkN-0-81d8d773a00677218a02356c4abb5b9c)
关于如何实现一个完整版的ls命令本书不再赘述,大家可以自己思考并试着实现。如果实在不知道怎么写,则可以参考ls命令的源代码实现。