opendir、readdir和closedir函数

注意: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.

猜你喜欢

转载自blog.csdn.net/qq_33883085/article/details/88720910