目录扫描程序详解

来源:互联网 发布:c 游戏编程 百度网盘 编辑:程序博客网 时间:2024/06/05 21:18

linux程序设计 第4版  第104页

#include<unistd.h>#include<stdio.h>#include<dirent.h>#include<string.h>#include<sys/stat.h>#include<stdlib.h>void printdir(char *dir, int depth){        DIR *dp;        struct dirent *entry;        struct stat statbuf;        if ((dp = opendir(dir)) == NULL)        {                fprintf(stderr, "cannot open directory: %s\n", dir);                return;        }        chdir(dir);        while ((entry = readdir(dp)) != NULL)        {                lstat(entry->d_name, &statbuf);                if (S_ISDIR(statbuf.st_mode))                {                        if (strcmp(".", entry->d_name) == 0 ||                                strcmp("..", entry->d_name) == 0)                                continue;                        printf("%*s%s/\n", depth, "", entry->d_name);                        printdir(entry->d_name, depth+4);                }                else printf("%*s%s\n", depth, "", entry->d_name);        }        chdir("..");        closedir(dp);}int main(){        printf("Directory scan of /home:\n");        printdir("/home", 0);        printf("done. \n");        exit(0);}


这个程序扫描 /home目录并输出。

初看也是一头雾水,于是进行具体函数分析:

14:原型:DIR *opendir(const char *name) : 打开一个目录并建立一个目录流,如果成功,它返回一个指向DIR结构的指针,该指针用于读取目录数据项,失败时返回一个

        空指 针。此处返回的指针为dp ,dp在第10 行已经被定义为 DIR结构,此结构在头文件 dirent.h 头文件中,作为目录操作的基础。此行语句判断若打开目录失败的情况

16: 原型:int fprintf(FILE *stream, const char *format, ...) :把自己的输出送到一个指定的文件流。

          此处为:若上面的 目录打开失败,则返回  cannot open directory 到标准错误stderr中

19: 原型:int chdir(const char *path):像shell中cd命令切换目录一样。此处为 若打开目录成功,则进入该目录

20: 原型:struct dirent *readdir(DIR *dirp):返回一个指针,该指针指向的结构里保存着目录流dirp中下一个目录项的有关资料,后续的 readdir 调用将返回后续的目录项,

         发生错误返回NULL。此处entry已在第11行定义为对应类型,

22:原型:int lstat(const char *path, struct stat *buf):通过文件名查找对应状态信息,statbuf已在第12行定义为相应类型,entry为dirent结构,该结构中包含

        ino_t  d_ino: 文件的inode节点号,char d_name[ ] : 文件的名字,mode_t st_mode: 文件权限与类型信息 ,等。此处通过文件名查找信息

23:S_ISDIR为宏定义,测试statbuf.st_mode是否是目录

25~27:跳过 d_name 为  .  和  ..  的数据项

28:printf("%*s%s/\n", depth, "", entry->d_name);  % *s  代表输出depth长度的""(空格)。输出目录名,并在每个目录后加上 /

29:printdir 函数调用自己并再次进入下一层目录处理,并缩进4个字节 。

31:如果不是目录,则名字后面不加 /

33:返回上级目录,从而可继续上级目录的遍历(通过29行调用)

34:原型:int closedir(DIR *dirp):关闭一个目录流并释放与之关联的资源   

39:主函数调用printfdir ,扫描/home目录,初始缩进为0

40:程序结束时 输出:done.  

 程序虽小,包含的函数还真不少,开始对函数不熟悉,现在都放一起分析下,整个程序畅通多了。