DIR *opendir(const char *dirpath);
DIR *pDir = NULL; //储存获取的目录流,给readdir作为参数
- 返回值:NULL 打开目录失败
- opendir()函数打开由 dirpath 指定的目录,并返回指向 DIR 类型结构的指针
DIR 类型结构
:目录流(directory stream)- 即调用者传递给下述其他函数的句柄
- 一旦从 opendir()返回,则将目录流指向目录列表的首条记录。
struct dirent *readdir(DIR *dirp);
struct dirent *dir_entry = NULL; // 存储获取的目录内容
- 返回值:NULL说明获取目录内容失败或者目录内容已经全部读取完成
- 每调用 readdir()一次,就会从 dirp 所指代的目录流中读取下一目录条目,并返回dirent 类型结构的指针
dirent 类型结构
:由静态分配而得到- 每次调用 readdir()都会覆盖该结构
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字符 */
}
- readdir()返回时并未对文件名进行排序,而是按照文件在目录中出现的天然次序
- 一旦遇到目录结尾或是出错,readdir()将返回 NULL
- 出错时会设置 errno 以示具体错误
- 所以可以进行如下区分
int closedir(DIR *dirp);
- 返回值:0正常 -1错误
- 头文件
#include <sys/stat.h>
#include <dirent.h>
readdir函数返回的是一个dirent结构体指针,这个dirent结构体中包含的d_name(文件名)就是我们需要的。
所以整个的ls命令实现流程为:
1.opendir打开指定目录
循环:{
2.readdir获得目录中每一个文件的dirent结构体
3.打印结构体中的d_name字符串
}
4.closedir关闭指定目录
- 实现简单的ls命令
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<dirent.h>
#include<string.h>
//函数声明
void do_ls(const char*);//完成ls命令的函数
void show_ls(struct dirent*);//打印ls结果的函数
void error_handle(const char*);//处理文件打开失败时的函数
int main(int argc,char* argv[])
{
//对输入的命令进行参数判断与处理
if(argc == 1){
//只输入了:ls
do_ls("."); // .表示当前文件夹,..表示当前文件夹的父文件夹。
}
else{
while(--argc){
do_ls(*(++argv));
}
}
return 0;
}
//主流程
void do_ls(const char* dir_name)
{
DIR* cur_dir = NULL;
struct dirent* cur_item4 = NULL;
//打开目录
if((cur_dir = opendir(dir_name)) == NULL){
//dir_name为目录名
error_handle(dir_name);
}
else{
//读取目录并显示信息
while((cur_item = readdir(cur_dir)) != NULL){
//文件夹里默认存在.和..,直接跳过 ( 这一步不一定要??)
if(strcmp(ent->d_name,".")==0||strcmp(ent->d_name,"..")==0) continue;
show_ls(cur_item);
}
printf("\n");
//关闭目录
closedir(cur_dir);
}
}
//显示(打印)文件名
void show_ls(struct dirent* cur_item){
printf("%s",cur_item->d_name); //d_name为dirent结构体里保存文件名的字符串
printf("\n");
}
//错误处理
void error_handle(const char* dir_name){
perror(dir_name);
exit(1);
}
注:需要注意的一个点是,.和..
是在Unix 以及所有类unix系统中,在文件夹中默认生成的,.表示当前文件夹, ..表示当前文件夹的父文件夹
。通常我们是不需要两个隐藏文件夹的,因此在遍历的时候直接跳过了。