文件IO -- 目录的操作(实现 ls -l 的功能)

1.打开目录  --  opendir

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

   DIR *opendir(const char *name);
   参数:
   	name:要打开的目录名
   返回值:
   	成功返回目录流指针,返回NULL;

2.读取目录 --  readdir

注:readdir 一次只能随机读取一个目录项

#include <dirent.h>

   struct dirent *readdir(DIR *dirp);
   
          struct dirent {
               char           d_name[256]; /*文件名*/
           };

注意它的返回值类型是结构体,所以在调用时就要定义同类型(struct dirent)的变量来接收它 

3.关闭目录  --  closedir

  #include <sys/types.h>

   #include <dirent.h>

   int closedir(DIR *dirp);
   
   参数:
   	dirp:目录流指针
   返回值:
   	成功返回0,失败返回-1

4.获取文件属性  --  lstat

 #include <sys/types.h>
   #include <sys/stat.h>
   #include <unistd.h>

   int stat(const char *pathname, struct stat *statbuf);
   int fstat(int fd, struct stat *statbuf);
   int lstat(const char *pathname, struct stat *statbuf);
   参数:
   	pathname:文件名
   	statbuf:存放文件信息的结构体地址
   返回值:
   	成功返回0,失败返回-1;
    
    struct stat
    {
               mode_t    st_mode;        //文件类型和权限
               nlink_t   st_nlink;       //文件硬链接数
               uid_t     st_uid;         //用户ID
               gid_t     st_gid;         //用户组ID
               off_t     st_size;        //文件大小
               struct timespec st_mtim;  //最后修改文件时间

           	   #define st_mtime st_mtim.tv_sec
	}

    
        #include <sys/types.h>
        #include <grp.h>

       struct group *getgrnam(const char *name);

       struct group *getgrgid(gid_t gid);

	
    	getgrgid -- 得到用户组名的函数
	    getpwuid -- 得到用户名的函数

这里注意lstat的形参也是结构体形,这里把这个结构体的成员也罗列出来了,还罗列了getgrgid 和 getpwuid 函数;

5.获取文件类型

 S_IFMT     0170000   bit mask for the file type bit field

 S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO
	
			如果 st_mode & S_IFMT等于对应文件类型宏,则文件类型宏对应类型就为文件类型
	
	获取文件权限:
			st_mode & 对应权限宏 == 宏本身 表示具有该权限

		   S_IRUSR     00400   owner has read permission
           S_IWUSR     00200   owner has write permission
           S_IXUSR     00100   owner has execute permission

	       S_IRGRP     00040   group has read permission
           S_IWGRP     00020   group has write permission
           S_IXGRP     00010   group has execute permission
	
		   S_IROTH     00004   others have read permission
           S_IWOTH     00002   others have write permission
           S_IXOTH     00001   others have execute permission

 

 6.例子--用目录IO操作实现 ls -l 的功能

/*===============================================
*   文件名称:myls.c
*   创 建 者:zhouhao  
*   创建日期:2022年08月06日
*   描    述:
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <grp.h>
#include <pwd.h>

int main(int argc, char *argv[])
{ 
    int ret = 0;
    struct stat info;    //创建存放文件信息的结构体
    struct tm *t = NULL;   //存放时间信息的结构体
    struct group *gp = NULL;   //存放用户组信息的结构体
    struct passwd *usr = NULL;  //存放用户信息的结构体

    DIR *dir = opendir(".");   //打开目录得到目录流指针
    if(NULL == dir)
    {
        perror("opendir");
        return -1;
    }

    struct dirent *buf = NULL;    

    while( (buf = readdir(dir)) != NULL)   //循环遍历目录得到每一个目录项
    {
        if(buf->d_name[0] != '.')    //不显示隐藏文件
        {
            
            ret = lstat(buf->d_name, &info);   //通过文件名得到文件信息
            if(ret < 0)
            {
                perror("lstat");
                return -1;
            }
                
            char stmode[20];

	memset(stmode, '-', sizeof(stmode));

	if(S_ISREG(info.st_mode)) /* regular file */
	{
		stmode[0] = '-';
	}
	if(S_ISDIR(info.st_mode))
    {
		stmode[0] = 'd';
	}
	if(S_ISCHR(info.st_mode))
	{
		stmode[0] = 'c';
	}
	if(S_ISBLK(info.st_mode))
	{
		stmode[0] = 'b';
	}
    if(S_ISFIFO(info.st_mode))
	{
		stmode[0] = 'p';
	}
	if(S_ISLNK(info.st_mode))
	{
		stmode[0] = 'l';
	}      
	if(S_ISSOCK(info.st_mode))
	{
		stmode[0] = 's';
	}
	/*解析权限位*/
	if(info.st_mode & S_IRUSR) 
	{
		stmode[1] = 'r';
	}
	if(info.st_mode & S_IWUSR) 
	{
		stmode[2] = 'w';
	}
	if(info.st_mode & S_IXUSR) 
	{
		stmode[3] = 'x';
	}
	if(info.st_mode & S_IRGRP) 
	{
		stmode[4] = 'r';
	}
	if(info.st_mode & S_IWGRP) 
	{
		stmode[5] = 'w';
	}
	if(info.st_mode & S_IXGRP) 
	{
		stmode[6] = 'x';
	}
	if(info.st_mode & S_IROTH) 
	{
		stmode[7] = 'r';
	}
	if(info.st_mode & S_IWOTH) 
	{
		stmode[8] = 'w';
	}
	if(info.st_mode & S_IXOTH) 
	{
		stmode[9] = 'x';
	}
	stmode[10] = '\0';

            printf("%s",stmode);//打印文件类型和文件权限

			
			printf("%ld  ", info.st_nlink);  //打印硬链接数
			
			usr = getpwuid(info.st_uid);
			printf("%s  ", usr->pw_name);    //打印用户名
			
			gp = getgrgid(info.st_gid);
			printf("%s  ", gp->gr_name);     //打印用户组名
			
			
			printf("%-8ld ", info.st_size);  //打印文件大小
			
			t = localtime(&info.st_mtime);
			printf("%d月  %d  %02d:%02d  ", t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min);                                    //打印最后一次修改文件时间

            printf("%s\n", buf->d_name);      //打印文件名
        }
    }


    closedir(dir);
    return 0;
} 

     

   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值