实现自己的ls命令 实现自己的ls命令

实现自己的ls命令
实现自己的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("
");
            }
        }
        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("  33[34m%-10s 33[0m
",name);
            }
            else
            {
                printf(" %-10s
",name);
            }
    }
    else
    {
        if(S_ISDIR(buf.st_mode))
        {
            printf("  33[34m%-10s 33[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 输出username
{
    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
"); //与以上不匹配,报错
    }
    return 0;
}