注意:在Linux中,目录的输入格式:/mnt//fghs、/mnt/fghs、/mnt/fghs和/mnt/fghs//是等效的,都一样。
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
返回值:出错返回NULL,并可以通过perror函数查看详细错误信息;成功,则返回一个DIR *类型的指针,该指针指向一个DIR类型的结构体,该结构体描述了所打开的目录的一些信息。可以类比open函数:FILE * fp=open( );打开一个文件,则返回一个FILE *类型的指针:包含了文件描述符、文件读写指针和I/O缓冲区三部分。则打开一个目录,返回一个DIR *类型的指针(目录指针),利用该指针可以对打开的目录进行读操作和关闭该目录。
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
作用:读一个打开了的目录,该函数可以自动遍历目录内部所有的文件,一个个自动进行遍历,直到全部遍历完。
返回值:成功,则返回一个struct dirent *类型的指针,指向struct dirent *结构体,该结构体包含了该目录中某一个文件的详细信息,包括:
struct dirent
{
ino_t d_ino; // 此目录进入点(该文件)的inode
ff_t d_off; // 目录文件开头至此目录进入点的位移(目录内文件为1,目录内的目录内部文件为2等等)
signed short int d_reclen; // d_name 的长度, 不包含NULL字符(0、\0)
unsigned char d_type; // d_name 所指的文件类型
har d_name[256]; // 文件名(字符串类型)
}; //后两个成员常用,记住!!
对于d_type的说明(宏定义):DT_BLK 块设备文件 DT_CHR 字符设备 DT_DIR 目录文件 DT_LNK 软链接文件 DT_FIFO管道文件 DT_REG 普通文件 DT_SOCK 套接字文件 DT_UNKNOW 未知 -D_BSD_SOURCE 编译时添加宏定义
则遍历到哪一个文件,则就返回该文件对应的struct dirent结构体。遍历完目录内部的最后一个文件后,会返回NULL,因此判断一个目录是否遍历完,判断其返回值是否为NULL即可,此时不代表出错,因此不会改变errno的值。若函数出错,也会返回NULL,且会修改errno的值。
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
作用:关闭目录文件 注意,打开目录后,不要忘记关闭。
返回值:0 成功 -1失败
//递归读一个目录,统计一个目录内部所有普通文件的个数(注意是递归,包括子目录)。
[root@localhost dir_op]# vim read_file_num.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int countFileNum( const char * ); //函数声明int countFileNum( const char *dirName ) //定义一个统计普通文件数目的函数
{DIR *dir=NULL;dir = opendir(dirName); //打开需要统计的目录if( dir == NULL ){perror("opendir");exit(1);}struct dirent *fx = NULL;fx = readdir( dir ); //读该目录,注意是每读一次,就自动遍历到下一个文件,因此必须要读一次,才能遍历到下一个文件。if( fx == NULL ){perror("readdir");exit(1);}int total=0;char buff[1024]={0}; //建立缓冲区while( fx ) //fx为NULL,则循环结束{if( strcmp(fx->d_name , ".") == 0 || strcmp( fx->d_name , "..") == 0 ){fx = readdir( dir ); //必须读一次,否则陷入死循环continue;} //字符串比较函数,排除.和..(当前目录和上级目录)if( fx->d_type == DT_DIR ) //如果是目录文件,则递归调用,注意递归思想{sprintf( buff,"%s/%s",dirName,fx->d_name ); //d_name只是目录本身的名字,不包含路劲(上级目录等)total += countFileNum( buff );}if( fx->d_type == DT_REG )total++;fx = readdir( dir ); //必须要读一次,否则不会遍历下一个文件}int qw = 0;qw = closedir(dir);if( qw==-1 ){perror("closedir");exit(1);} //关闭目录return total;
}int main( int argc , char *argv[ ] )
{if( argc < 2 ){printf( "./a.out dirName\n");exit(1);}int num = 0;num = countFileNum( argv[1] );printf( " the number of reg file is %d.\n",num);return 0;
}
[root@localhost dir_op]# gcc -pipe -Wall -pedantic -ggdb3 read_file_num.c -o read_file_num
[root@localhost dir_op]# ls
a.out chdir chdir.c fileNum fileNum.c haha.c hehe.c mkdir.c mytest opendir.c readdir.c read_file_num read_file_num.c
[root@localhost dir_op]# ./read_file_num .
the number of reg file is 13. //成功统计出当前目录中的普通文件数为13.