(以下内容部分来自 Beginning Linux Programing)
要求
- 目录中的每个文件单独列在一行上
- 每个子目录会在它的名字后面加上一个斜线字符‘/’
- 子目录中的文件在缩进四个空格后一次排列
需要调用的结构体和函数原型
-
struct DIR
上面是DIR结构体的定义,它是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息。struct __dirstream { void *__fd; char *__data; int __entry_data; char *__ptr; int __entry_ptr; size_t __allocation; size_t __size; __libc_lock_define (, __lock) }; typedef struct __dirstream DIR;
-
struct dirent
从上述定义能够看出,dirent结构体存储的关于文件的信息很少,主要是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。readdir函数读取到的文件名存储在结构体dirent的d_name成员中struct dirent { long d_ino; /* inode number 索引节点号 */ off_t d_off; /* offset to this dirent 在目录文件中的偏移 */ unsigned short d_reclen; /* length of this d_name 文件名长 */ unsigned char d_type; /* the type of d_name 文件类型 */ char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */ }
- struct stat
struct stat { mode_t st_mode; //文件访问权限 ino_t st_ino; //索引节点号 dev_t st_dev; //文件使用的设备号 dev_t st_rdev; //设备文件的设备号 nlink_t st_nlink; //文件的硬连接数 uid_t st_uid; //所有者用户识别号 gid_t st_gid; //组识别号 off_t st_size; //以字节为单位的文件容量 time_t st_atime; //最后一次访问该文件的时间 time_t st_mtime; //最后一次修改该文件的时间 time_t st_ctime; //最后一次改变该文件状态的时间 blksize_t st_blksize; //包含该文件的磁盘块的大小 blkcnt_t st_blocks; //该文件所占的磁盘块 };
从上述定义可以看出,结构体stat主要用来保存文件的具体信息,不同于dirent只是保存文件名的索引。该结构体用在函数stat()中,下面会细说。
上述几个结构体的定义,引用自blog 菜鸟的逆袭
-
opendir
#include <sys/types.h> #include <dirent.h>
DIR *opendir(const char *pathname)
作用是打开一个目录,并建立一个目录流。若成功返回指向DIR结构的指针,该指针用于读取目录数据项。该指针将作为参数传给readdir()、closedir()
-
readir
#include <sys/types.h> #include <dirent.h> int closedir(DIR *dirp)
struct dirent *readdir(DIR *dirp)
readdir函数将返回一个指针,指针指向的结构体里保存着,下一个目录项的有关信息 -
chdir
#include <unistd.h> int chdir(const char *pathname)
该函数的作用类似于shell中的cd命令,用来切换目录
-
closedir
该函数关闭一个目录流,并且释放与之相关的资源。执行成功返回0,发生错误返回-1#include <sys/types.h> #include <dirent.h> int closedir(DIR *dirp)
-
lstat与stat
#include <unistd.h> #include <sys/stat.h> #include <sys/types.h> int stat(const char *pathname, struct stat *buf); int lstat(const char *pathname, struct stat *buf);
函数stat与lstat返回的是通过文件名查到的状态信息。他们的结果基本一致,但当文件是一个符号链接时,lstat返回的是该符号链接本身的信息,而stat返回的是该链接指向的文件的信息
printdir()源码
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
void printdir(char *dir, int depth)
{
/* DIR结构体类似于FILE,是一个内部结构,readdir(),opendir()等几
* 个函数用这个内部结构保存当前正在被读取的目录的有关信息
* */
DIR *dp;
/*dirent不仅仅指向目录,还指向目录中的具体文件.dirent结构体存储的关于
* 文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类
* 似ls -l那种效果的文件信息,必须要靠stat函数了
*/
struct dirent *entry;
/*
* 函数readdir读取到的文件名存储在结构体成员dirent.d_name中,函数
* stat通过d_name文件名来获取文件的详细信息,存储在stat结构体中
*/
struct stat statbuf;
if((dp = opendir(dir)) == NULL)
{
fprintf(stderr, "cannot open directory!\n");
return;
}
chdir(dir);/* 进入目录 */
while((entry = readdir(dp)) != NULL)
{
/*
* 原型:int lstat(const char *path, struct stat *buf)
* 作用:给定具体路径,读取文件相关信息
*/
lstat(entry->d_name, &statbuf);
/* 测试是否是目录,通过宏定义S_ISDIR,来实现该功能*/
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%4d\n", depth, "", entry->d_name, statbuf.st_size);
}
}
chdir("..");
closedir(dp);
}
main()源码
#include<stdio.h>
#include <stdlib.h>
/* 该头文件中只有一行内容:void printdir(char *, int) */
#include "printdir.h"
int main(int argc, char* argv[])
{
char *topdir = ".";
if(argc >= 2)
{
topdir = argv[1];
}
printf("Directory scan of %s\n", topdir);
printdir(topdir, 0);
printf("Done.\n");
exit(0);
}
编译执行
gcc -c printdir.c main.c
gcc -o printdir.o main.o
./main
若没有参数,那么默认遍历当前文件夹下的所有文件并输出
./main ../
该命令输出上一级目录下的所有文件名和大小