Linux 目录访问(opendir/closedir/readdir)

opendir

DIR *opendir(const char *dirpath);

DIR *pDir = NULL; //储存获取的目录流,给readdir作为参数

  • 返回值:NULL 打开目录失败
  • opendir()函数打开由 dirpath 指定的目录,并返回指向 DIR 类型结构的指针
    • DIR 类型结构:目录流(directory stream)
    • 即调用者传递给下述其他函数的句柄
    • 一旦从 opendir()返回,则将目录流指向目录列表的首条记录

readdir

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 以示具体错误
    • 所以可以进行如下区分
    • 在这里插入图片描述

closedir

int closedir(DIR *dirp);

  • 返回值:0正常 -1错误

头文件

#include <sys/stat.h>
#include <dirent.h>

实现简单的ls框架

在这里插入图片描述

readdir函数返回的是一个dirent结构体指针,这个dirent结构体中包含的d_name(文件名)就是我们需要的。
所以整个的ls命令实现流程为:

1.opendir打开指定目录
循环:{
2.readdir获得目录中每一个文件的dirent结构体
3.打印结构体中的d_name字符串
}
4.closedir关闭指定目录

在里只是打印出文件名而已,如果要获得文件的具体信息,再通过stat()函数得到


实现简单的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系统中,在文件夹中默认生成的.表示当前文件夹, ..表示当前文件夹的父文件夹。通常我们是不需要两个隐藏文件夹的,因此在遍历的时候直接跳过了。

参考:Linux系统编程【3.1】——编写ls命令

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值