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