[Linux&C语言] Linux系统命令“ls -l”的实现

Linux系统命令“ls -l”的实现

一、基本概念

  1. “ls -l”所显示各项的意义

  例:-rw-rw-r--   1  using using  3102  7月 22 17:06  test.c

    drwxrwxr-x  2  using using  4096  7月 22 18:39  testdir

    lrwxrwxrwx  1  using using      17   7月 22 18:43  shared -> /media/sf_shared/

  第一字段:首字母代表的是文件类型 ,其中"-"为普通文件、"d"为目录文件、"c"为字符设备文件、"b"为块设备文件、"p"为管道文件、"l"为链接文件、"s"为socket文件。三个“rwx”依次代表文件所有者、文件所有者所在用户组、其它用户对文件拥有的权限。“rwx”分别代表拥有读、写和执行权限,“-”代表无对应权限。

  第二字段:文件硬连接数量

  第三字段:文件拥有者

  第四字段:文件拥有者所在组

  第五字段:文件大小(以字节为单位)

  第六字段:文件最后更改时间

  第七字段:文件名(若为连接文件则追加显示其源文件的路径)

  

二、重要函数与结构体

  1. 目录操作函数

 1        #include <sys/types.h>
 2        #include <dirent.h>
 3
 4        DIR *opendir(const char *name);
 5        DIR *fdopendir(int fd);
 6
 7
 8        #include <dirent.h>
 9
10        struct dirent *readdir(DIR *dirp);
11
12            struct dirent {
13                ino_t          d_ino;       /* inode number */
14                off_t          d_off;       /* offset to the next dirent */
15                unsigned short d_reclen;    /* length of this record */
16                unsigned char  d_type;      /* type of file; not supported by all file system types */
17                char           d_name[256]; /* filename */
18            };

  2. 获取文件信息

  这里必须使用int lstat(const char *path, struct stat *buf);函数,否则在处理链接文件时会将其链接的原文件作为处理对象,而不是它本身。

 1        #include <sys/types.h>
 2        #include <sys/stat.h>
 3        #include <unistd.h>
 4
 5        int stat(const char *path, struct stat *buf);
 6        int fstat(int fd, struct stat *buf);
 7        int lstat(const char *path, struct stat *buf);
 8
 9            struct stat {
10                dev_t     st_dev;     /* ID of device containing file */
11                ino_t     st_ino;     /* inode number */
12                mode_t    st_mode;    /* protection */
13                nlink_t   st_nlink;   /* number of hard links */
14                uid_t     st_uid;     /* user ID of owner */
15                gid_t     st_gid;     /* group ID of owner */
16                dev_t     st_rdev;    /* device ID (if special file) */
17                off_t     st_size;    /* total size, in bytes */
18                blksize_t st_blksize; /* blocksize for file system I/O */
19                blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
20                time_t    st_atime;   /* time of last access */
21                time_t    st_mtime;   /* time of last modification */
22                time_t    st_ctime;   /* time of last status change */
23            };

  3. 文件类型及权限的判断

 1        The following POSIX macros are defined to check the file type using the st_mode field:
 2
 3            S_ISREG(m)  is it a regular file?
 4            S_ISDIR(m)  directory?
 5            S_ISCHR(m)  character device?
 6            S_ISBLK(m)  block device?
 7            S_ISFIFO(m) FIFO (named pipe)?
 8            S_ISLNK(m)  symbolic link? (Not in POSIX.1-1996.)
 9            S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
10
11
12        The following flags are defined for the st_mode field:
13
14            S_IFMT     0170000   bit mask for the file type bit fields
15            S_IFSOCK   0140000   socket
16            S_IFLNK    0120000   symbolic link
17            S_IFREG    0100000   regular file
18            S_IFBLK    0060000   block device
19            S_IFDIR    0040000   directory
20            S_IFCHR    0020000   character device
21            S_IFIFO    0010000   FIFO
22            S_ISUID    0004000   set UID bit
23            S_ISGID    0002000   set-group-ID bit (see below)
24            S_ISVTX    0001000   sticky bit (see below)
25            S_IRWXU    00700     mask for file owner permissions
26            S_IRUSR    00400     owner has read permission
27            S_IWUSR    00200     owner has write permission
28            S_IXUSR    00100     owner has execute permission
29            S_IRWXG    00070     mask for group permissions
30            S_IRGRP    00040     group has read permission
31            S_IWGRP    00020     group has write permission
32            S_IXGRP    00010     group has execute permission
33            S_IRWXO    00007     mask for permissions for others (not in group)
34            S_IROTH    00004     others have read permission
35            S_IWOTH    00002     others have write permission
36            S_IXOTH    00001     others have execute permission

  4. 文件用户ID与用户所在组ID的转换

 1        #include <sys/types.h>
 2        #include <pwd.h>
 3
 4        struct passwd *getpwnam(const char *name);
 5        struct passwd *getpwuid(uid_t uid);
 6        int getpwnam_r(const char *name, struct passwd *pwd,char *buf, size_t buflen, struct passwd **result);
 7        int getpwuid_r(uid_t uid, struct passwd *pwd,char *buf, size_t buflen, struct passwd **result);
 8
 9
10         The passwd structure is defined in <pwd.h> as follows:
11
12            struct passwd {
13                char   *pw_name;       /* username */
14                char   *pw_passwd;     /* user password */
15                uid_t   pw_uid;        /* user ID */
16                gid_t   pw_gid;        /* group ID */
17                char   *pw_gecos;      /* user information */
18                char   *pw_dir;        /* home directory */
19                char   *pw_shell;      /* shell program */
20            };
 1        #include <sys/types.h>
 2        #include <grp.h>
 3
 4        struct group *getgrnam(const char *name);
 5        struct group *getgrgid(gid_t gid);
 6        int getgrnam_r(const char *name, struct group *grp,char *buf, size_t buflen, struct group **result);
 7        int getgrgid_r(gid_t gid, struct group *grp,char *buf, size_t buflen, struct group **result);
 8
 9
10        The group structure is defined in <grp.h> as follows:
11
12            struct group {
13                char   *gr_name;       /* group name */
14                char   *gr_passwd;     /* group password */
15                gid_t   gr_gid;        /* group ID */
16                char  **gr_mem;        /* group members */
17            };

  5. 文件最后修改时间

 1        #include <time.h>
 2
 3        struct tm *localtime(const time_t *timep);
 4        struct tm *localtime_r(const time_t *timep, struct tm *result);
 5
 6
 7        Broken-down time is stored in the structure tm which is defined in <time.h> as follows:
 8
 9            struct tm {
10                int tm_sec;         /* seconds */
11                int tm_min;         /* minutes */
12                int tm_hour;        /* hours */
13                int tm_mday;        /* day of the month */
14                int tm_mon;         /* month */
15                int tm_year;        /* year */
16                int tm_wday;        /* day of the week */
17                int tm_yday;        /* day in the year */
18                int tm_isdst;       /* daylight saving time */
19            };

三、执行结果及对比

 

 

四、优点与改进方向

  本博是在博友“Apollon_krj”的一篇博客“Linux&C编程之Linux系统命令“ls -l”的简单实现”的基础上改进完成。总体沿用了原有思路和框架,做了以下改良:

  1. 可以处理软连接文件(原处理链接文件所链接的原文件);

  2. 当输入“myls -l”指令时默认显示当前目录下文件的详细信息(原报错);

  3. 指令、代码优化。

  但目前暂未实现总用量/total、模糊匹配和彩字显示功能,有兴趣的朋友可以尝试一下。

五、实现代码

  1. myls.h

 1 #ifndef _MYLS_H_
 2 #define _MYLS_H_
 3
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6 #include<string.h>
 7 #include<unistd.h>
 8 #include<dirent.h>
 9 #include<sys/stat.h>
10 #include<sys/types.h>
11 #include<fcntl.h>
12 #include<time.h>
13 #include<pwd.h>
14 #include<grp.h>
15
16 // 处理错误
17 void error_printf(const char* );
18
19 // 处理路径下的文件
20 void list_dir(const char* );
21 void list_message(const char* , const struct stat*);
22
23 // 所显示的文件信息
24 void file_type(const struct stat* );
25 void file_power(const struct stat* );
26 // printf st_nlink
27 void file_id(const struct stat* );
28 // printf st_size
29 void file_mtime(const struct stat* );
30 // printf filename
31 void link_printf(const char* );
32
33 #endif//_MYLS_H_

  2. myls.c

  1 #include "myls.h"
  2
  3 // 处理错误
  4 void error_printf(const char* funname)
  5 {
  6     perror(funname);
  7     exit(EXIT_FAILURE);
  8     /*
  9     * EXIT_SUCCESS和EXIT_FAILURE是两个常量。
 10     * EXIT_SUCCESS=0,EXIT_FAILURE=1。
 11     * 0表示程序寿终正寝,1表示死于非命。
 12     */
 13 }
 14
 15 // 读取路径下的文件
 16 void list_dir(const char* pathname)
 17 {
 18     DIR* ret_opendir = opendir(pathname); // 打开目录"pathname"
 19     if(ret_opendir == NULL)
 20         error_printf("opendir");
 21
 22     int ret_chdir = chdir(pathname); // 改变工作目录至"pathname",便于stat函数的使用
 23     if(ret_chdir == -1)
 24         error_printf("chdir");
 25
 26     struct dirent* ret_readdir = NULL; // 定义readdir函数返回的结构体变量
 27     while(ret_readdir = readdir(ret_opendir)) // 判断是否读取到目录尾
 28     {
 29         char* filename = ret_readdir->d_name; // 获取文件名
 30         struct stat file_message = {}; // 定义stat函数返回的结构体变量
 31         int ret_stat = lstat(filename, &file_message); // 获取文件信息
 32         if(ret_stat == -1) // stat读取文件错误则输出提示信息
 33             printf("%s error!", filename);
 34         else if(strcmp(filename,".") && strcmp(filename,"..")) // 不输出当前目录与上一级目录
 35             list_message(filename, &file_message);
 36     }
 37 }
 38
 39 // 打印所读取文件的信息
 40 void list_message(const char* filename, const struct stat* file_message)
 41 {
 42     file_type(file_message); // 判断打印文件类型
 43     file_power(file_message); // 判断并打印文件权限
 44     printf("%d ", file_message->st_nlink); // 打印硬链接数
 45     file_id(file_message); // 转换并打印用户id与组id
 46     printf("%5ld ", file_message->st_size); // 打印文件大小
 47     file_mtime(file_message); // 打印文件最后修改时间
 48     printf("%s ", filename); // 打印文件名
 49     if(S_ISLNK(file_message->st_mode)) // 如果是软链接文件,打印其指向的位置
 50         link_printf(filename);
 51     puts("");
 52 }
 53
 54
 55 // 所显示的文件信息
 56 void file_type(const struct stat* file_message)
 57 {
 58     //mode_t mode = (*get_message).st_mode;
 59     mode_t mode = file_message->st_mode;
 60
 61     if     (S_ISREG(mode))  printf("-"); // 普通文件
 62     else if(S_ISDIR(mode))    printf("d"); // 目录文件
 63     else if(S_ISCHR(mode))    printf("c"); // 字符设备文件
 64     else if(S_ISBLK(mode))    printf("b"); // 块设备文件
 65     else if(S_ISFIFO(mode))    printf("p"); // 管道文件
 66     else if(S_ISLNK(mode))  printf("l"); // 链接文件
 67     else                    printf("s"); // socket文件
 68 }
 69
 70 void file_power(const struct stat* file_message)
 71 {
 72     mode_t mode = file_message->st_mode;
 73
 74     // 判断USR权限
 75     printf("%c", mode&S_IRUSR?‘r‘:‘-‘);
 76     printf("%c", mode&S_IWUSR?‘w‘:‘-‘);
 77     printf("%c", mode&S_IXUSR?‘x‘:‘-‘);
 78
 79     // 判断GRP权限
 80     printf("%c", mode&S_IRGRP?‘r‘:‘-‘);
 81     printf("%c", mode&S_IWGRP?‘w‘:‘-‘);
 82     printf("%c", mode&S_IXGRP?‘x‘:‘-‘);
 83
 84     // 判断OTH权限
 85     printf("%c", mode&S_IROTH?‘r‘:‘-‘);
 86     printf("%c", mode&S_IWOTH?‘w‘:‘-‘);
 87     printf("%c ", mode&S_IXOTH?‘x‘:‘-‘);
 88 }
 89
 90 void file_id(const struct stat* file_message)
 91 {
 92     // 根据用户id获取用户名
 93     struct passwd* pwd;
 94     pwd = getpwuid(file_message->st_uid);
 95     printf("%s ",pwd->pw_name);
 96
 97     // 根据组id获取组名
 98     struct group* grp;
 99     grp = getgrgid(file_message->st_gid);
100     printf("%s ",grp->gr_name);
101
102     #if 0
103     struct passwd
104     {
105         char * pw_name; /* Username, POSIX.1 */
106         char * pw_passwd; /* Password */
107         __uid_t pw_uid; /* User ID, POSIX.1 */
108         __gid_t pw_gid; /* Group ID, POSIX.1 */
109         char * pw_gecos; /* Real Name or Comment field */
110         char * pw_dir; /* Home directory, POSIX.1 */
111         char * pw_shell; /* Shell Program, POSIX.1 */
112     };
113
114     struct group
115     {
116         char *gr_name;  /* Group name */
117         char *gr_passwd;  /* password */
118         __gid_t gr_gid;  /* Group ID */
119         char **gr_mem;  /* Member list */
120     }
121     #endif//0
122 }
123
124 void file_mtime(const struct stat* file_message)
125 {
126     struct tm* t = localtime(&file_message->st_mtime);
127     printf("%2d月 %2d %02d:%02d ", t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min);
128 }
129
130 void link_printf(const char* filename)
131 {
132     char buf[1024] = "123";
133     if(0 == readlink(filename, buf, sizeof(buf)))
134         error_printf("readlink");
135     printf("-> %s ",buf);
136 }

  3. main_myls.c

 1 #include "myls.h"
 2
 3
 4 int main(const char argc, const char** argv)
 5 {
 6     char path[1024] = {};
 7
 8     if(argc == 2 && !(strcmp(argv[1],"-l"))) // 判断命令格式
 9         strcpy(path,"./");
10     else if(argc != 3)
11     {
12         printf("格式有误! \n");
13         exit(EXIT_FAILURE);
14     }
15     else
16         strcpy(path,argv[2]);
17
18     if(!(strcmp(argv[1],"-l")))
19     {
20         struct stat file_message = {};
21         int ret_stat = stat(path, &file_message);
22
23         if(ret_stat == -1)
24                error_printf("stat");
25
26         if(S_ISDIR(file_message.st_mode)) // 判断是否为目录
27             list_dir(path);
28         else
29             list_message(path, &file_message);
30     }
31     else
32     {
33         printf("error in main!\n");
34         exit(EXIT_FAILURE);
35     }
36     return 0;
37 }

原文地址:https://www.cnblogs.com/usingnamespace-caoliu/p/9351773.html

时间: 2024-10-08 08:55:57

[Linux&C语言] Linux系统命令“ls -l”的实现的相关文章

Linux&amp;C编程之Linux系统命令“ls -l”的简单实现

一.基础知识: 1.获取文件详细信息的函数: (1).获取文件信息的函数: #include<sys/stat.h> int stat(const char * path,struct stat * buf);/*将path参数(文件或目录)的文件信息写到buf中,buf为传出参数*/ (2).文件信息结构体: /*用不到的成员被注释掉,只需了解需要的成员即可*/ struct stat{ //dev_t st_dev;/*设备id号*/ //ino_t st_ino;/*i节点号*/ mod

linux一步一脚印--- ls -l 命令执行显示结果的每一列含义

转截:https://blog.csdn.net/zhuoya_/article/details/77418413 上面图片转截于首处连接,后面是通过文字作简单描述:1.第一颜色框,文件类型列,这里简单描述几种常见类型,d表示目录文件,例如dr-xr-xr-x:l表示链接文件,例如lrwxr-xr-x:-表示普通文件,例如-rwxrwxr-x:2.第二三四颜色框,文件权限列,因为linux是多用户多任务系统,每个用户对同一个文件的权限可能都不一样,所以对文件的权限设置是非常重要的:3.第五个颜色

设置ll和ls -l命令中显示的日期格式

在Linux中使用ll或者ls -l命令过程中,日期的显示总是显示英文日期,觉的很不爽,那么怎么设置显示的格式是按照我们定义的呢? 1.临时更改显示样式,当回话结束后恢复原来的样式 export TIME_STYLE='+%Y-%m-%d %H:%M:%S'    # 直接在命令中执行即可 2.永久改变显示样式,更改后的效果会保存下来 修改/etc/profile文件,在文件内容末尾加入     export TIME_STYLE='+%Y-%m-%d %H:%M:%S' 执行如下命令,使你修改

高仿linux下的ls -l命令——C语言实现

主要用到的函数可以参考头文件,仅仅支持ls -l这功能,扩展就交给大家了0.0 相关测试图片: ? ? 话不多说,直接上码 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <sys/stat.h> 5 #include <sys/types.h> 6 #include <string.h> 7 #include <time.h

linux 常用命令ll 即 ls -l --color=auto

1.linux系统运维或者开发中,经常会用到ll 即 ls -l --color=auto 命令.比如 ll -hF, <span style="font-size:18px;">[[email protected] ~]$ ll -hF 总用量 1.1G drwxrwxr-x. 2 doctor doctor 4.0K 1月 18 10:23 Documents/ -rw-r-----. 1 doctor doctor 701M 12月 24 21:51 Far123-X

编程实现Linux下的ls -l

头文件 #ifndef __FUNC_H__ #define __FUNC_H__ #include<stdio.h> #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> #inc

linux中ls、ls -l、ls -al、ll命令

ls只是简单的列出目录下文件名,ll更加详细的列出了文件的类型.文件所有者权限.文件所有者组权限.文件大小.文件最后修改时间,etc... 我们可以用一个简单的图来说明,如下图1: 图1 1.第一位就"-",表示普通文件. 2.rw- ,表示文件所有者对Text.txt文件有读.写权限,(x位置为"-"表示没有执行权限) 3.rw- ,表示文件所有者所在组对Text.txt文件有读.写权限,(x位置为"-"表示没有执行权限) 4.r--  ,表示

linux ls -l 详解[转]

linux ls -l 详解[转] 有几个字段老是记不住,就记载这里吧 ls -l 列表信息详解 我们平时用ls -l 命令查看一个目录下的文件和子目录的详悉信息时,会得到一个详细的文件和目录名列表.这个列表包含了文件的属性,所属用户,所属组,创建时间,文件大小等等信息.这些信息到底是什么意思呢?有很多初学者对这些不太了解,因此想详悉讲解一下用ls -l命令得到的文件列表每一个字段的意思 以笔者电脑的/root目录为例: [[email protected] root]# ll 总用量 4055

【转】linux ls -l的详解

原文:http://blog.csdn.net/sjzs5590/article/details/8254527 以root的家目录为例: 可以看到,用ls -l命令查看某一个目录会得到一个7个字段的列表. 第1行:总计(total) Total后面的数字是指当前目录下所有文件所占用的空间总和.可以使用ls –lh查看,也可使用ls –alh查看. 第1字段: 文件属性字段 -rw-r--r-- 1 root root 762 07-29 18:19 exit 文件属性字段总共有10个字母组成: