输出目录下所有文件

Linux下DIR_dirent_stat等结构体详解

摘自:http://www.liweifan.com/2012/05/13/linux-system-function-files-operation/

最近在看Linux下文件操作相关章节,遇到了这么几个结构体,被搞的晕乎乎的,今日有空,仔细研究了一下,受益匪浅。

首先说说DIR这一结构体,以下为DIR结构体的定义:

1.             struct __dirstream  

2.                {  

3.                 void *__fd;    

4.                 char *__data;    

5.                 int __entry_data;    

6.                 char *__ptr;    

7.                 int __entry_ptr;    

8.                 size_t __allocation;    

9.                 size_t __size;    

10.             __libc_lock_define (, __lock)   

11.            };  

12.           

13.         typedef struct __dirstream DIR;  

 

DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息(摘自《UNIX环境高级编程(第二版)》)。

函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针,而该指针由以下几个函数使用:

 

1.             struct dirent *readdir(DIR *dp);   

2.               

3.             void rewinddir(DIR *dp);   

4.               

5.             int closedir(DIR *dp);   

6.               

7.             long telldir(DIR *dp);   

8.               

9.             void seekdir(DIR *dp,long loc);  

 

关于DIR结构,我们知道这么多就可以了,没必要去再去研究他的结构成员。

接着是dirent结构体,首先我们要弄清楚目录文件(directory file)的概念:这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针(摘自《UNIX环境高级编程(第二版)》)。从定义能够看出,dirent不仅仅指向目录,还指向目录中的具体文件,readdir函数同样也读取目录下的文件,这就是证据。以下为dirent结构体的定义:

 

1.             struct dirent  

2.             {  

3.               long d_ino; /* inode number 索引节点号 */  

4.                  

5.                 off_t d_off; /* offset to this dirent 在目录文件中的偏移 */  

6.                  

7.                 unsigned short d_reclen; /* length of this d_name 文件名长 */  

8.                  

9.                 unsigned char d_type; /* the type of d_name 文件类型 */  

10.              

11.             char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */  

12.         }  

 

从上述定义也能够看出来,dirent结构体存储的关于文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。

通过readdir函数读取到的文件名存储在结构体dirent的d_name成员中,而函数

int stat(constchar *file_name, struct stat *buf);

的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中。以下为stat结构体的定义:

 

1.             struct stat {  

2.               

3.                     mode_t     st_mode;       //文件访问权限   

4.               

5.                     ino_t      st_ino;       //索引节点号   

6.               

7.                     dev_t      st_dev;        //文件使用的设备号   

8.               

9.                     dev_t      st_rdev;       //设备文件的设备号   

10.           

11.                 nlink_t    st_nlink;      //文件的硬连接数   

12.           

13.                 uid_t      st_uid;        //所有者用户识别号   

14.           

15.                 gid_t      st_gid;        //组识别号   

16.           

17.                 off_t      st_size;       //以字节为单位的文件容量   

18.           

19.                 time_t     st_atime;      //最后一次访问该文件的时间   

20.           

21.                 time_t     st_mtime;      //最后一次修改该文件的时间   

22.           

23.                 time_t     st_ctime;      //最后一次改变该文件状态的时间   

24.           

25.                 blksize_t st_blksize;    //包含该文件的磁盘块的大小   

26.           

27.                 blkcnt_t   st_blocks;     //该文件所占的磁盘块   

28.           

29.               };  

 

这个记录的信息就很详细了吧,呵呵。

最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?

首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。

接着,我们调用readdir( c)函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。

然后,我们遍历d,调用lstat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。

总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。

 

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>

void printdir(char *dir, int depth)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
	
	//返回指向目录dir的DIR结构体指针dp
    if((dp = opendir(dir)) == NULL) 
	{
        fprintf(stderr,"cannot open directory: %s\n", dir);
        return;
    }
	//进到dir指向的目录下
    chdir(dir);
	//readdir(dp)函数读取目录dir下所有文件[包括目录],返回指向目录dir下所有文件的dirent *entry
    while((entry = readdir(dp)) != NULL) 
	{
		//调用lstat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体statbuf中
        lstat(entry->d_name,&statbuf);
        if(S_ISDIR(statbuf.st_mode)) 
		{
            /* Found a directory, but ignore . and .. */
            if(strcmp(".",entry->d_name) == 0 || 
                strcmp("..",entry->d_name) == 0)
                continue;
            printf("%*s%s/\n",depth,"",entry->d_name);
            /* Recurse at a new indent level */
            printdir(entry->d_name,depth+4);
        }
        else printf("%*s%s\n",depth,"",entry->d_name);
    }
    chdir("..");
    closedir(dp);
}

/*  Now we move onto the main function.  */

int main()
{
    printf("--------------------------------------------------------------\n");
    printdir("./",0);
    printf("--------------------------------------------------------------\n");

    exit(0);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值