• IO学习系列之使用文件IO的接口在一个目录下,实现Linux命令“ls -l”的功能


    • 实例要求:
    • 使用文件IO的接口在一个目录下,实现Linux命令“ls -l”的功能;
    • 实例分析:
    • 正常使用“ls -l”命令,会出现以下内容:
    /*
     -    rwxrw-rw-                                1          linux      linux          26                10月2 14:31    x.txt
    文件类型  所属用户的权限\所属组的权限\其他人的权限 硬链接个数  所属用户    所属组      大小(字节)       时间戳       文件名
    */
    
    • 1
    • 2
    • 3
    • 4
    • 相关的文件IO接口函数如下:
    • opendir函数:
    	 #include 
    	 #include 
    	 DIR *opendir(const char *name);
    	 /*
    	 功能:打开一个目录文件
    	 
    	 参数name:目录名
    	 
    	 返回值:
    	 
        	成功:  目录指针
        	
        	失败:  NULL 重置错误码
         */
    	 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • readdir函数:
    	 #include 
    	 struct dirent *readdir(DIR *dirp);
    	 /*
    	 功能:读取目录下的内容
    	 
    	 参数:目录指针
    	 
    	 返回值:
    	 
        	成功:  dirent结构体指针
        	
        	失败:  NULL  重置错误码
        */
        // dirent结构体指针
        struct dirent {
            ino_t          d_ino;       /* 读到的文件的inode号 */
            off_t          d_off;       /* 无需关注 */
            unsigned short d_reclen;    /* 这个结构体的大小 不是文件的大小 */
            unsigned char  d_type;      /* 文件类型 */
                DT_BLK      This is a block device.
                DT_CHR      This is a character device.
                DT_DIR      This is a directory.
                DT_FIFO     This is a named pipe (FIFO).
                DT_LNK      This is a symbolic link.
                DT_REG      This is a regular file.
                DT_SOCK     This is a UNIX domain socket.
            char           d_name[256]; /* 文件名 */
        };
    	 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • closedir函数:
    	#include 
    	#include 
    	int closedir(DIR *dirp);
    	/*
    	功能:关闭一个目录
    	
    	参数dirp:目录指针
    	
    	返回值:
    	
        	成功:  0
        	
        	失败:  -1  重置错误码
        */
    	
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • stat函数:
    	#include 
    	#include 
    	#include 
    	int stat(const char *pathname, struct stat *statbuf);
    	/*
    	功能:
    	
        	获取文件的属性信息
        	
    	参数:
    	
        	pathname:文件的路径和名字
        	
        	statbuf:用来保存文件属性的结构体
           
    	返回值:
    	
        	成功  0
        	失败  -1  重置错误码
    	*/
    	//文件属性的结构体
    	 struct stat {
                dev_t     st_dev;         /* 文件所在磁盘的设备号 */
                ino_t     st_ino;         /* inode号 */
                mode_t    st_mode;        /* 文件的类型和访问模式 */
                    //S_IFMT     0170000   文件类型的掩码
                    //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  
                    if((S_IFMT & st_mode) == S_IFREG){//注意优先级问题
                        printf("普通文件\n");
                    }
                    //或者用下面的宏判断
                    if(S_ISREG(m)){
                        printf("普通文件\n");
                    }
                    
                    //st_mode & 0777 == 文件的权限
                nlink_t   st_nlink;       /* 硬链接的个数 */
                uid_t     st_uid;         /* 所属用户的id */
                gid_t     st_gid;         /* 所属组的id */
                dev_t     st_rdev;        /* 设备号 字符设备文件或者块设备文件使用 */
                off_t     st_size;        /* 总大小 单位字节 */
                blksize_t st_blksize;     /* 块的大小 */
                blkcnt_t  st_blocks;      /* 块的数量 */
                struct timespec st_atim;  /* 最后一次访问的时间 */
                struct timespec st_mtim;  /* 最后一次修改的时间 */
                struct timespec st_ctim;  /* 最后一次状态改变的时间 */
                //下面的宏定义是为了方便获取时间戳里的秒数的
                #define st_atime st_atim.tv_sec      /* Backward compatibility */
                #define st_mtime st_mtim.tv_sec
                #define st_ctime st_ctim.tv_sec
            };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • getpwuid函数:
    	#include 
        #include 
        struct passwd *getpwuid(uid_t uid);
        /*
    	功能:
    	
        	根据uid获取用户信息
        	
    	参数:
    	
        	uid: 用户id
        	
    	返回值:
    	
        	成功: 	用户信息结构体
        	
        	失败:  	NULL  重置错误码
    	 */
    	 //用户信息结构体
    	 struct passwd {
            char   *pw_name;       /* username */
            char   *pw_passwd;     /* user password */
            uid_t   pw_uid;        /* user ID */
            gid_t   pw_gid;        /* group ID */
            char   *pw_gecos;      /* user information */
            char   *pw_dir;        /* home directory */
            char   *pw_shell;      /* shell program */
        };
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • getgrgid函数:
    	 #include 
    	 #include 
    	 struct group *getgrgid(gid_t gid);
    	 /*
    	功能:
    	
        	根据gid获取组信息
        	
    	参数:
        	gid: 组id
        	
    	返回值:
    	
        	成功 组信息结构体
        	失败  NULL  重置错误码
        */
        struct group {
            char   *gr_name;        /* group name */
            char   *gr_passwd;      /* group password */
            gid_t   gr_gid;         /* group ID */
            char  **gr_mem;         /* NULL-terminated array of pointers to names of group members */
        };
    	 
    	 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • sprintf函数:
    	#include 
    	int sprintf(char *str, const char *format, ...);
    	/*
    	功能:
    	
        	将格式化的信息写入str指向的缓冲区中
        	
    	参数:
    	
        	str:		自定义的缓冲区的首地址
        	
        	format:	格式
        	
        	...:		可变参
        	
    	返回值:
    	
        	成功:  		格式化的字符的个数
        	
        	失败:  		小于0的值
        */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 示例代码:
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    //所属用户权限宏定义
    #define U_R 0400
    #define U_W 0200
    #define U_X 0100
    
    //所属组权限宏定义
    #define G_R 0040
    #define G_W 0020
    #define G_X 0010
    
    //其他人权限宏定义
    #define O_R 0004
    #define O_W 0002
    #define O_X 0001
    
    int main(int argc, const char *argv[])
    {
        //入参合理性检查
        if (2 != argc)
        {
            printf("Usage : %s dir_name\n", argv[0]);
            return -1;
        }
        // 打开目录
        DIR *my_dir = opendir(argv[1]);
        if (NULL == my_dir)
        {
            perror("opendir error");
            return -1;
        }
    
        //文件的类型
        char type = '-';
    
        //所属用户权限赋初值
        char u_r = '-';
        char u_w = '-';
        char u_x = '-';
    
        //所属组权限赋初值
        char g_r = '-';
        char g_w = '-';
        char g_x = '-';
    
        //其他人权限赋初值
        char o_r = '-';
        char o_w = '-';
        char o_x = '-';
    
        int nlink = 0;
    
        char u_name[64] = {0};
    
        char g_name[64] = {0};
    
        int size = 0;
    
        char date[128] = {0};
    
        char path_name[512] = {0};
    
    
    
        struct tm *p = NULL;
    
        struct stat lk;
    
        struct dirent *dir = NULL;
    
        int mode = 0;
       
        
    
        while (NULL != (dir = readdir(my_dir)))
        {   
            //过滤隐藏文件
            if ('.' == *(dir->d_name))
            {
                continue;
            }
    
    
            //文件类型
            switch (dir->d_type)
            {
            
            
                case DT_BLK:
                    type = 'b';
                    break;
    
                case DT_SOCK:
                    type = 's';
                    break;
    
                case DT_FIFO:
                    type = 'p';
                    break;
    
                case DT_REG:
                    type = '-';
                    break;
    
                case DT_LNK:
                    type = 'l';
                    break;
    
                case DT_CHR:
                    type = 'c';
                    break;
    
                case DT_DIR:
                    type = 'd';
                    break;
                
           
            
            }
    
            //数组清零
            memset(path_name, 0, sizeof(path_name));
    
    
            //组装路径
            sprintf(path_name, "%s/%s", argv[1], dir->d_name);
    
    
            if (stat(path_name, &lk))
            {
                perror("stat error");
                return -1;
            }
    
            u_r = '-';
            u_w = '-';
            u_x = '-';
    
            
            g_r = '-';
            g_w = '-';
            g_x = '-';
    
    
            o_r = '-';
            o_w = '-';
            o_x = '-';
    
    
            // 文件权限
            mode = lk.st_mode & 0777;
    
    
            if (mode & U_R)
            {
                u_r = 'r';
            }
            if (mode & U_W)
            {
                u_w = 'w';
            }
            if (mode & U_X)
            {
                u_x = 'x';
            }
    
    
            if (mode & G_R)
            {
                g_r = 'r';
            }
            if (mode & G_W)
            {
                g_w = 'w';
            }
            if (mode & G_X)
            {
                g_x = 'x';
            }
    
    
    
            if (mode & O_R)
            {
                o_r = 'r';
            }
            if (mode & O_W)
            {
                o_w = 'w';
            }
            if (mode & O_X)
            {
                o_x = 'x';
            }
    
            //硬链接的个数
            nlink = lk.st_nlink;
    
            //所属用户名
            strcpy(u_name, getpwuid(lk.st_uid)->pw_name);
    
    
            //所属组名
            strcpy(g_name, getgrgid(lk.st_gid)->gr_name);
    
            //文件的大小(字节)
            size = lk.st_size;
    
            //时间戳(最后一次修改的时间)
            p = localtime(&(lk.st_mtime));
    
            sprintf(date, "%2d月%2d %02d:%02d", p->tm_mon + 1, \
                            p->tm_mday, p->tm_hour, p->tm_min);
    
            //输出文件的基本内容
            printf("%c%c%c%c%c%c%c%c%c%c %d %s %s %7d %s %-s\n",\
                   type, u_r, u_w, u_x, g_r, g_w, g_x, o_r, o_w, o_x, nlink,\
                   u_name, g_name, size, date, dir->d_name);
        }
    
        // 关闭目录
    
        closedir(my_dir);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 运行结果:
    linux@ubuntu:~$ ./a.out ./
    -rw-rw-r-- 1 linux linux     730 101 22:44 k1.c
    -rw-rw-r-- 1 linux linux      26 101 22:40 k2.txt
    -rwxrwxr-x 1 linux linux   12984 102 19:31 a.out
    -rw-rw-r-- 1 linux linux    4078 102 19:17 ls-l.c
    drwxrwxr-x 2 linux linux    4096 102 18:59 k3
    linux@ubuntu:~$ ls -l
    总用量 32
    -rwxrwxr-x 1 linux linux 12984 102 19:31 a.out
    -rw-rw-r-- 1 linux linux   730 101 22:44 k1.c
    -rw-rw-r-- 1 linux linux    26 101 22:40 k2.txt
    drwxrwxr-x 2 linux linux  4096 102 18:59 k3
    -rw-rw-r-- 1 linux linux  4078 102 19:17 ls-l.c
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 本示例代码,仅供参考;
  • 相关阅读:
    数据分析:从界定问题开始做数据分析?
    MacOS原版镜像iso下载
    膜拜!国际程序设计师,用图、文、码就解剖了Java多线程设计模式
    WebSocket协议:5分钟从入门到精通
    总结一次系统底层学习笔记
    安装opencv-python
    安装React脚手架
    Mini-Gemini: Mining the Potential of Multi-modality Vision Language Models论文解读
    PTA_乙级_1001_C++
    矩阵求导之二
  • 原文地址:https://blog.csdn.net/qq_41878292/article/details/133492630