• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

主要用到的函数可以参考头文件,仅仅支持ls -l这功能,扩展就交给大家了0.0

相关测试图片:

 

编译 gcc -std=c99 ls_l.c -o ls

运行 ./ls -l

( 请勿在文件结构复杂的目录下执行,程序会挂的!)

话不多说,直接上码

  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>
  8 #include <pwd.h>
  9 #include <grp.h>
 10 #include <time.h>
 11 #include <dirent.h>
 12 
 13 #define MAX_FILE_NUM 200
 14 
 15 
 16 //可能还有一些小问题没有解决,功能基本已经实现,如有建议,望大佬赐教
 17 
 18 typedef struct LS
 19 {
 20     char mode[15];    // 文件的模式
 21     int dir_num;    // 是否目录或目录中包含目录的数量
 22     char user[20];    // 文件的用户名
 23     char group[20];    // 文件的组名
 24     long size;        // 文件的字节数
 25     char time[30];    // 文件的最后修改时间
 26     char year[5];    // 拓展用,年份
 27     char mon[5];    // 月份
 28     char hour[5];    //
 29     char min[5];    //
 30     int st_mode;    // 文件类型和权限
 31     char name[20];    // 文件名
 32 }LS; 
 33 
 34 // 获取文件的模式
 35 char* file_mode(mode_t m,char* str)
 36 {
 37     if(S_ISREG(m))
 38         str[0] = '-';
 39     else if(S_ISDIR(m))
 40         str[0] = 'd';
 41     else if(S_ISCHR(m))
 42         str[0] = 'c';
 43     else if(S_ISBLK(m))
 44         str[0] = 'b';
 45     else if(S_ISFIFO(m))
 46         str[0] = 'q';
 47     else if(S_ISLNK(m))
 48         str[0] = 'l';
 49 //    else if(S_ISSOCK(m))
 50 //        str[0] = 's';
 51     else 
 52         str[0] = '?';
 53 
 54     str[1] = '\0';
 55 
 56     strcat(str,S_IRUSR&m?"r":"-");
 57     strcat(str,S_IWUSR&m?"w":"-");
 58     strcat(str,S_IXUSR&m?"x":"-");
 59 
 60     strcat(str,S_IRGRP&m?"r":"-");
 61     strcat(str,S_IWGRP&m?"w":"-");
 62     strcat(str,S_IXGRP&m?"x":"-");
 63     
 64     strcat(str,S_IROTH&m?"r":"-");
 65     strcat(str,S_IWOTH&m?"w":"-");
 66     strcat(str,S_IXOTH&m?"x":"-");
 67 
 68     return str;
 69 }
 70 
 71 // 获取目录的数量
 72 int dir_count(char* path)
 73 {
 74     DIR *dir;
 75     dir = opendir(path);
 76     struct dirent *dirent;
 77     int count = 0;
 78     while((dirent = readdir(dir)) != NULL)
 79     {
 80         if(dirent->d_type == 4)
 81             count++;
 82     }
 83     closedir(dir);
 84     return count;
 85 }
 86 
 87 // 是否是目录或目录下有目录
 88 int is_dir(struct dirent *dirent)
 89 {
 90     char* a = dirent->d_name;
 91     if(dirent->d_type == 8)
 92         return 1;
 93     if(dirent->d_type == 4)
 94     {
 95         if(dir_count(a) == 0)
 96             return 2;
 97         else
 98             return dir_count(a);
 99     }
100 }
101 
102 // 获取用户名
103 char* file_user(uid_t st_uid,char* str)
104 {
105     struct passwd *user;
106     user = getpwuid(st_uid);
107     sprintf(str,"%s",user->pw_name);
108     return str;
109 }
110 
111 // 获取组名
112 char* file_group(uid_t st_uid,char* str)
113 {
114     struct passwd *user;
115     user = getpwuid(st_uid);
116     struct group *grp;
117     grp = getgrgid(user->pw_gid);
118     sprintf(str,"%s",grp->gr_name);
119     return str;
120 }
121 
122 // 获取文件大小
123 off_t file_size(struct stat buf)
124 {
125     off_t size = buf.st_size;
126     return size;
127 }
128 
129 // 获取最后修改时间
130 char* file_time(time_t mt,char* str)
131 {
132     struct tm* t = localtime(&mt);
133     sprintf(str,"%d月 %02d %02d:%02d",t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min);
134     return str;
135 }
136 
137 // 获取文件的数量
138 int file_count(char* path)
139 {
140     DIR *dir;
141     dir = opendir(path);
142     struct dirent *dirent;
143     int count = 0;
144     while((dirent = readdir(dir)) != NULL)
145     {
146         count++;
147     }
148     closedir(dir);
149     return count;
150 }
151 
152 // 交换
153 void equal(LS *a,LS *b)
154 {
155     strcpy(a->mode,b->mode);
156     a->dir_num = b->dir_num;
157     strcpy(a->user,b->user);
158     strcpy(a->group,b->group);
159     a->size = b->size;
160     strcpy(a->time,b->time);
161     a->st_mode = b->st_mode;        
162     strcpy(a->name,b->name);
163 }
164 
165 // 排序
166 void sort(LS *info,int index)
167 {
168     LS *temp = (LS*)malloc(sizeof(LS));
169     for(int i=index-1; i>0; i--)
170     {
171         for(int j=0; j<i; j++)
172         {
173             if(strcmp(info[i].name,info[j].name)<0)
174             {
175                 equal(temp,&info[i]);
176                 equal(&info[i],&info[j]);
177                 equal(&info[j],temp);
178             }
179         }
180     }
181 }
182 
183 // 输出结构体
184 void show_ls(LS *info,int index)
185 {
186     for(int i=0; i<index; i++)
187     {    
188         //printf("%d: ",i);
189         printf("%s \033[0m",info[i].mode);
190         printf("%d ",info[i].dir_num);
191         printf("%s ",info[i].user);
192         printf("%s ",info[i].group);
193         printf("%5ld ",info[i].size);
194         printf(" %s ",info[i].time);
195         //printf("%d ",info[i].st_mode);        
196         if(16893 == info[i].st_mode)
197         {
198             // 颜色
199             printf("\033[34m\033[1m%s\033[0m",info[i].name);
200         }
201         else if(33277 == info[i].st_mode)
202         {
203             printf("\033[32m\033[1m%s\033[0m",info[i].name);
204         }
205         else
206         {
207             printf("%s",info[i].name);
208         }
209         if(i < index)
210             printf("\n");
211     }
212     //printf("循环结束\n");
213 }
214 
215 // 创建结构体,赋值
216 LS *create(struct stat buf,struct dirent *dirent)
217 {
218     LS* info = (LS*)malloc(sizeof(LS));
219     char str[50] = {};
220     //puts(file_mode(buf.st_mode,str));
221     strcpy(info->mode,file_mode(buf.st_mode,str));
222     //puts(info->mode);
223     info->dir_num = is_dir(dirent);
224     strcpy(info->user,file_user(buf.st_uid,str));
225     strcpy(info->group,file_group(buf.st_uid,str));
226     info->size = file_size(buf);
227     strcpy(info->time,file_time(buf.st_mtime,str));
228     info->st_mode = buf.st_mode;        
229     strcpy(info->name,dirent->d_name);
230 
231     return info;
232 }
233 
234 int main(int argc,char* argv[])
235 {
236     LS info[MAX_FILE_NUM];
237     char* l = "-l";
238     if(argc != 2)
239     {
240         printf("仅支持传入 -l\n");
241         return 1;
242     }
243     if(strcmp(argv[1],l) != 0)
244     {
245         printf("\"ls:无法识别的选项\"%s\"\n",argv[1]);
246         printf("请尝试执行\"ls --help\"来获取更多信息。\n");
247         return 0;
248     }
249     char* a = ".";
250     char* b = "..";
251     char* path = malloc(10000);
252     strcpy(path,"./");    // 只支持当前路径
253     int count = file_count(path);
254 
255     DIR *dir;
256     dir = opendir(path);
257     struct dirent *dirent;
258     int index = 0;    // 结构体下标
259     int blocks = 0;
260     for(int i=0; i<count; i++)
261     {
262         dirent = readdir(dir);
263         struct stat buf = {};
264         if(stat(dirent->d_name,&buf))
265         {
266             perror("stat");
267             return -1;
268         }
269 
270         // 跳过特殊情况
271         if(strcmp(dirent->d_name,a)==0 || strcmp(dirent->d_name,b)==0)
272             continue;
273         blocks += buf.st_blocks;
274         //printf("%d\n",blocks);
275         info[index++] = *create(buf,dirent);
276     }
277     closedir(dir);
278     //printf("文件总数:%d\n",index);
279     //show_ls(info,index);    
280 
281     printf("总用量 %d\n",blocks/2);
282     sort(info,index);
283     show_ls(info,index);
284     return 0;
285 }

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap