实现自己的ls命令
估计每个使用过linux系统的人都知道ls是啥吧。也相信大家都对ls的简单命令烂熟于心了吧,这里就不想再赘述了,直接进入正题吧。 代码里面会有许多注释,相信的家一定能看懂的。 说明:此代码我在kail linux下编译无任何错误,运行也基本无bug,相信大家在一般linux下运行也无问题。
代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <linux/limits.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#define MAX_STRING 255 /*最长文件名,linux系统下规定文件名不允许超过255个字符,当然文件夹也是,因为文件夹就是特殊的文件。*/
//链表头插法初始化,这里使用的是宏定义来进行链表操作的,很高端,come on ,你也可以的
#define List_Init(list,list_node_t){ \
list=(list_node_t *)malloc(sizeof(list_node_t)); \
list->next=NULL; \
}
//链表头插法宏定义
#define List_AddHead(list,newNode){ \
newNode->next=list->next; \
list->next=newNode; \
}
typedef struct str_sort //结构体,里面仅保存问价名
{
char str[256];
struct str_sort *next;
}str_node_t;
//函数声明部分
void my_stat(int flag,char *name);
void my_err(const char *err_string,int line);
char *analy_filetype(struct stat *buf);
void print_filemode_usr(struct stat *buf);
void print_filemode_gro(struct stat *buf);
void print_filemode_oth(struct stat *buf);
void print_usr_name(struct stat *buf);
void print_gro_name(struct stat *buf);
void print_time(time_t st_time);
int display(int flag,char *path);
void sort(int count,str_node_t *head);
int print_info_srv(int count,int flag,str_node_t *head);
int display(int flag,char *path) //文件目录解析函数,获取当前目录所有文件
{
int i=0,j,count=0;
DIR *dir;
struct dirent *ptr;
char cwd[256];
getcwd(cwd,256); //记录当前的目录
chdir(path); //转到path所代表的目录下
str_node_t *newNode,*head;
List_Init(head,str_node_t);
if((dir=opendir(path))==NULL)
{
perror("opendir");
return -1;
}
while((ptr=readdir(dir))!=NULL)
{
i++;
newNode=(str_node_t *)malloc(sizeof(str_node_t));
strcpy(newNode->str,ptr->d_name);
List_AddHead(head,newNode); //头插法建立新链表
}
count=i;
print_info_srv(count,flag,head);
closedir(dir);
chdir(cwd); //转到先前的目录
}
int print_info_srv(int count,int flag,str_node_t *head) //打印文件信息服务函数
{
int i;
str_node_t *p;
sort(count,head); //对文件名进行排序
p=head;
for(i=0;i<count;i++)
{
p=p->next;
if(flag==-1 || flag==0)
{
if(!strcmp(p->str,".")||!strcmp(p->str,"..")||p->str[0]=='.')/*排除掉点和点点目录,以及以点开头的隐藏目录*/
{
continue;
}
my_stat(flag,p->str);
if(i==count-1)
{
printf("\n");
}
}
else
{
my_stat(flag,p->str);
}
}
}
void sort(int count,str_node_t *head) //文件名排序函数,使用的是冒牌排序法
{
int i,j;
char temp[256];
str_node_t *p;
for(i=1;i<=count;i++)
{
p=head->next;
for(j=1;j<count;j++)
{
if(strcmp(p->str,p->next->str)>0)
{
strcpy(temp,p->str);
strcpy(p->str,p->next->str);
strcpy(p->next->str,temp);
}
p=p->next;
}
}
}
void my_stat(int flag,char *name) //打印文件相关信息
{
struct stat buf;
lstat(name,&buf);
if(flag==0 || flag==2)
{
printf("%s",analy_filetype(&buf));
print_filemode_usr(&buf);
print_filemode_gro(&buf);
print_filemode_oth(&buf);
printf("%3d",buf.st_nlink);
print_usr_name(&buf);
print_gro_name(&buf);
printf("%6d",buf.st_size);
print_time(buf.st_mtime);
if(S_ISDIR(buf.st_mode))
{
printf(" \033[34m%-10s\033[0m\n",name);
}
else
{
printf(" %-10s\n",name);
}
}
else
{
if(S_ISDIR(buf.st_mode))
{
printf(" \033[34m%-10s\033[0m",name);
}
else
{
printf("%-14s",name);
}
}
}
char *month_analy(int month) //月份解析函数,linux底层是以0开始的,相信大家也并不意外
{
switch(month)
{
case 0:
return "Jan";
case 1:
return "Feb";
case 2:
return "Mar";
case 3:
return "Apr";
case 4:
return "May";
case 5:
return "Jun";
case 6:
return "Jul";
case 7:
return "Aug";
case 8:
return "Sep";
case 9:
return "Oct";
case 10:
return "Nov";
case 11:
return "Dec";
}
}
void print_time(time_t st_time) //日期解析函数
{
struct tm p;
gmtime_r(&st_time,&p);
printf(" %3s",month_analy(p.tm_mon));
if(p.tm_mday<10) //小于十的前面补零
{
printf(" 0%d",p.tm_mday); //小于十的前面补零
}
else
{
printf(" %2d",p.tm_mday);
}
if(p.tm_hour<2 || p.tm_hour>=23)
{
printf(" 0%d:",(p.tm_hour+8)); /*此处系统使用的是国际标准时间,中国位于东八区,比标准时间早8个小时,故要加上八*/
}
else
{
printf(" %2d:",p.tm_hour+8);
}
if(p.tm_min<10)
{
printf("0%d",p.tm_min);
}
else
{
printf("%2d",p.tm_min);
}
}
void my_err(const char *err_string ,int line)
{
fprintf(stderr,"line:%d",line);
perror(err_string);
exit(1);
}
char *analy_filetype(struct stat *buf) //文件类型解析函数
{
if(S_ISLNK(buf->st_mode))
{
return "l"; //符号链接
}
else if(S_ISREG(buf->st_mode))
{
return "-"; //普通文件
}
else if(S_ISDIR(buf->st_mode))
{
return "d"; //目录文件
}
else if(S_ISCHR(buf->st_mode))
{
return "c"; //字符特殊文件
}
else if(S_ISBLK(buf->st_mode))
{
return "b"; //块特殊文件
}
else if(S_ISFIFO(buf->st_mode))
{
return "f"; //命名管道
}
else if(S_ISSOCK(buf->st_mode))
{
return "s"; //套接字
}
}
void print_filemode_usr(struct stat *buf) //文件所有者
{
//文件所有者权限
if(buf->st_mode & S_IRUSR)
printf("r");
else
printf("-");
if(buf->st_mode & S_IWUSR)
printf("w");
else
printf("-");
if(buf->st_mode & S_IXUSR)
printf("x");
else
printf("-");
}
void print_filemode_gro(struct stat *buf) //文件所数组
{
//文件用户组权限
if(buf->st_mode & S_IRGRP)
printf("r");
else
printf("-");
if(buf->st_mode & S_IWGRP)
printf("w");
else
printf("-");
if(buf->st_mode & S_IXGRP)
printf("x");
else
printf("-");
}
void print_filemode_oth(struct stat *buf) //其他用户
{
//其他用户权限
if(buf->st_mode & S_IROTH)
printf("r");
else
printf("-");
if(buf->st_mode & S_IWOTH)
printf("w");
else
printf("-");
if(buf->st_mode & S_IXOTH)
printf("x ");
else
printf("- ");
}
void print_usr_name(struct stat *buf) //通过uid 输出用户名
{
struct passwd *pwd;
pwd=getpwuid(buf->st_uid);
printf(" %s",pwd->pw_name);
}
void print_gro_name(struct stat *buf) //通过gid输出用户组名a
{
struct group *gup;
gup=getgrgid(buf->st_gid);
printf(" %s",gup->gr_name);
}
int main(int argc,char **argv)
{
int flag; //flag=-1 [ls] flag=0 [ls -l] flag=1 [ls -a] flag=2 [ls -al/-la]
if(1==argc) //analysis: ls
{
flag=-1;
display(flag,".");
return 0;
}
else if(argc==2 && !strcmp("-l",argv[1])) //analysis: ls -l
{
flag=0;
display(flag,".");
}
else if(argc==2 && !strcmp("-a",argv[1])) //analysis: ls -a
{
flag=1;
display(flag,".");
}
else if(argc==2 && !strcmp("-al",argv[1])) //analysis: ls -al
{
flag=2;
display(flag,".");
}
else if(argc==2 && !strcmp("-la",argv[1])) //analysis : ls -la
{
flag=2;
display(flag,".");
}
else if(argc==2) //analysis: ls file
{
flag=-1;
display(flag,argv[1]);
}
else if(argc==3 && !strcmp("-l",argv[1])) //analysis: ls -l file
{
flag=0;
display(flag,argv[2]);
}
else if(argc==3 && !strcmp("-a",argv[1])) //analysis : ls -a file
{
flag=1;
display(flag,argv[2]);
}
else if(argc==3 && !strcmp("-al",argv[1])) //analysis :ls -al file
{
flag=2;
display(flag,argv[2]);
}
else if(argc==3 && !strcmp("-la",argv[1])) //analysis :ls -la file
{
flag=2;
display(flag,argv[2]);
}
else
{
printf("Not Support This Commond\n"); //与以上不匹配,报错
}
return 0;
}