实现一个ls命令 (-alR)

ls命令是我们平时可以说是用的最频繁的命令之一了 本文就来实现一个简单的ls命令

代码一共是实现了三个参数 -a -l -R 其中a与l可以说是比较简单的 我们只需要去解析命令行参数以及通过路径名来获取其下的文件 然后通过获取的文件名来进行状态的获取 就OK了 我们重点来说下-R命令的实现。

-R命令的实现(实现打印根目录)
先说下具体的实现方法 其实也很简单 就是像一般的ls一样 先便利一遍 记录其中的目录文件 然后记录下来 然后等遍历完我们需要的文件后再拿出刚刚保存的文件进行新一轮ls 往复循环 知道在一次循环后其中没有目录文件,那么我们的方法其实就很明确了 就是用栈 这里就出现了问题 1.使用递归 也就是系统栈 2.使用动态数组 用堆内存 模拟链表 实现一个栈 这又引出了一个问题 首先我们知道根目录下文件是非常多的 我们系统给予程序的栈内存是很有限的 只有区区8M 这足以满足我们一般的程序需要 但在一些情况下 比如我们要打印根目录 8M的栈内存就有点小了,(用动态数组当然无所谓了)。 所以

  1. 方法1
    使用递归 手动打系统默认分配给程序的栈开大 命令如下
ulimit -s 102400

这段命令所做的事情就是暂时将系统分配给程序的栈从8M提升到100M 当然你想永久这样的话将它挂到开机启动项中即可

然后就按照一般思路 递归即可
注意
**在写代码的过程中发现一个以前没有注意到的地方 就是stat与lstat的区别 在书上的概念虽然清楚 stat与lstat的区别就是lstat返回的是符号链接文件本身的信息 而不是它指向的文件的信息 就这一点不同 在代码中就是天差地别的 因为在递归根目录的时候确实是有符号链接文件指向一个目录文件的特殊文件存在 也就是说我们如果使用stat函数进行筛选的话 链接文件也会进入我们下一轮ls的名单 因为stat显示的是链接文件的指向 也就是那个目录文件 而下一轮ls会尝试对这个链接文件进行打开递归 就会出现问题 所以我们要使用lstat 在第一轮就把这个链接文件剔除 不进入下一轮递归 这应该就是这两个函数如此相思还是要分开的原因吧 **

  1. 方法2
    方法二其实和方法一差不多 只不过方法一使用的是系统栈 而方法二使用堆内存建立一个栈 也就是链表 用我们建立的栈去实现一个递归的过程 然后就没有了第一种情况爆栈的情况 再就是注意lstat的使用 就OK了

还有一点需要注意
**当我们打开/proc这个设备文件的目录的时候 很容易因为文件在检测时存在 而打开时不存在而出现段错误 所以我们要进行判断 **

我们如果想让我们的ls更像真实的ls 我们还可以把my_ls加入环境变量 使得任意目录都可以使用我们的ls 我们就需要去修改配置文件

  1. vim /etc/profile
  2. 在其中声明PATH之后的语句加入
export PATH=$PATH:/home/lizhaolong/suanfa/TeamF/LZL/Requirement

后面为ls存在的目录

  1. 因为linux只有在启动的时候才会加载profile这个系统整体的配置文件 所以我们只需要在加载一次profile文件即可
source /etc/profile

这样一个及其简化版ls就完成了

以下附上我的以及坤坤的代码 分别为递归写法与链表写法

参考思路即可

递归写法

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<dirent.h>
#include<pwd.h>
#include<errno.h>
#include<grp.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>

#define PARAM_NONE 0
#define PARAM_A    1
#define PARAM_L    2
#define PARAM_R    4
#define MAXROWLWN  80

int g_leave_len = MAXROWLWN;
int g_maxlen;  //存放某目录下最长文件名的长度


void recursion(int flag_param,char * path)//本函数的意义是递归显示目录下的文件
{
    DIR *dir;
    struct dirent *ptr;
    int count=0;
    char filename[7300][256],temp[256];
    char book[7300][256];
    int ans=0;
    dir=opendir(path);  //先打开一遍统计文件名数量
    if(dir==NULL)
    {
        my_err("opendir",__LINE__);
    }
    //统计出最长文件名长度和文件总数
    while((ptr=readdir(dir))!=NULL)
    {
        if(g_maxlen<strlen(ptr->d_name))
        {
            g_maxlen=strlen(ptr->d_name);
        }
        count++;
    }
    closedir(dir);
    if(count>7300)
    {
        my_err("too many file under this dir!\n",__LINE__);
    }
    printf("%d\n",count);
    int i,j,len=strlen(path);

    dir=opendir(path);
    struct stat buf;
    for(int i=0;i<count;i++)
    {
        ptr=readdir(dir);
        if(ptr==NULL) my_err("readdir",__LINE__);
        strncpy(filename[i],path,len);
        filename[i][len]='\0';  //因为strcat的实现需要最后一位是‘\0’
        if(filename[i][0]=='.') continue;
        strcat(filename[i],ptr->d_name);
        filename[i][len+strlen(ptr->d_name)]='\0';
        if(flag_param>=8)
        display(3,filename[i]);
        else 
        display(flag_param-4,filename[i]);
        //这里是为了使用没有R参数的显示函数 因为-R参数值为4
        //if(access(filename[i],0)==-1) return 0;
        lstat(filename[i],&buf);
        if(S_ISDIR(buf.st_mode))  //此文件是一个目录 应该递归显示
        {
            strcpy(book[ans++],filename[i]);
            //printf("hello:  %s\n",book[ans-1]);
        }  //保存下所有的目录文件
    }
    closedir(dir);
    if(flag_param & PARAM_L ==0)  //没有l的时候打印一个换行符
    putchar('\n');
    for(int k=0;k<ans;k++)
    {
        //printf("12: %s\n",book[k]);
        int flag=0;
        for(int i=0;i<strlen(book[k])-1;i++)
        {
            if(book[k][i]=='/' && book[k][i+1]=='.')
            {
                flag=1;
                break;
            }
        }
        if(flag) continue;
        printf("\n%s:\n",book[k]);
        recursion(flag_param,strcat(book[k],"/"));
        putchar('\n');
    }
}

void my_err(const char *err_string, int line)
{
    fprintf(stderr,"line:%d",line);
    perror(err_string);
    exit(1);
}

void display_attribute(struct stat buf,char * name)  /*显示所有的状态信息*/
{
    char   buf_time[32];
    struct passwd *psd;
    struct group  *grp;

    if(S_ISLNK(buf.st_mode)) {   //链接文件
        printf("l");
    }else if(S_ISREG(buf.st_mode)){  //普通文件
        printf("-");
    }else if(S_ISDIR(buf.st_mode)){  //目录
        printf("d");
    }else if(S_ISCHR(buf.st_mode)){  //字符设备
        printf("c");
    }else if(S_ISBLK(buf.st_mode)){   //块设备
        printf("b");
    }else if(S_ISFIFO(buf.st_mode)){  //FIFO文件
        printf("f");
    }else if(S_ISSOCK(buf.st_mode)){   //socket文件
        printf("s");
    }
    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("-");

    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("-");


    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("-");

    printf(" ");

    psd=getpwuid(buf.st_uid);
    grp=getgrgid(buf.st_gid);
    printf("%4d  ",buf.st_nlink);
    //printf("hello world\n");
    printf("%-8s",psd->pw_name);  //这里错误
    //printf("hello world\n");
    printf("%-8s",grp->gr_name);
    //printf("hello world\n");
    printf("%6d",buf.st_size);//文件的大小
    strcpy(buf_time,ctime(&buf.st_mtime));  //文件的最后修改时间
    //ctime函数的作用为把时间转化为字符串
    buf_time[strlen(buf_time)-1]='\0';
    printf("  %s",buf_time);
}

void display_single(char *name)
{
    int i,len;
    if(g_leave_len<g_maxlen)
    {
        putchar('\n');
        g_leave_len=MAXROWLWN;
    }

    len=strlen(name);
    len=g_maxlen-len;
    printf("%-s",name);
    for(int i=0;i<len;i++) putchar(' ');
    printf("  ");  //两个空格
    g_leave_len-=(g_maxlen+2);//一行中剩下的字符数
}

void display(int flag,char *pathname)  //传入一个路径名 
{
    //printf("%d ok\n",flag);
    int i,j;
    struct stat buf;
    char name[512];  //代表名称的最长值 不同系统可能不同
    //printf("ol  %s:",pathname);
    for(i=0,j=0;i<strlen(pathname);i++)
    {
        if(pathname[i]=='/')  //目录之间的分隔符
        {
            j=0;continue;
        }
        name[j++]=pathname[i];
    }
    name[j]='\0';
    char tmp[512];
    strcpy(tmp,name);
    if(lstat(pathname,&buf)==-1)
    {
        my_err("stat",__LINE__);  //stat函数出现错误 进行精确到行的报错
    } 
    switch (flag)
    {
        case PARAM_NONE:
            if(tmp[0]!='.')    //一般情况不显示隐藏文件
            display_single(tmp);
            break;
        case PARAM_A:
            display_single(tmp);
            break;
        case PARAM_L:
            if(tmp[0]!='.')
            {
                display_attribute(buf,tmp);
                printf("  %s\n",tmp);
            }
            break;
        case PARAM_A+PARAM_L:
                //printf("ok :  %s \n",pathname);
                display_attribute(buf,name);
                printf("  %s\n",tmp);
                break;
        default:
            break;
    }
}

void display_dir(int flag_param,char * path)
{
    //printf("%dbbb\n",flag_param);
    if(flag_param>=4) //证明有-R选项      //上面已经遍历此目录
    {
        recursion(flag_param,path);
    }else{
        DIR *dir;
        struct dirent *ptr;
        int count=0;
        char filename[7300][512];
        dir=opendir(path);  //先打开一遍统计文件名数量
        if(dir==NULL)
        {
            my_err("opendir",__LINE__);
        }
        //统计出最长文件名长度和文件总数
        while((ptr=readdir(dir))!=NULL)
        {
            if(g_maxlen<strlen(ptr->d_name))
            {
                g_maxlen=strlen(ptr->d_name);
            }
            count++;
        }
        closedir(dir);
        if(count>7300)
        {
            my_err("too many file under this dir!\n",__LINE__);
        }

        int i,j,len=strlen(path);

        dir=opendir(path);
        printf("%d:\n",count);
        for(int i=0;i<count;i++)
        {
            ptr=readdir(dir);
            if(ptr==NULL) my_err("readdir",__LINE__);
            
            strncpy(filename[i],path,len);
            filename[i][len]='\0';  //因为strcat的实现需要最后一位是‘\0’
            strcat(filename[i],ptr->d_name);
            filename[i][len+strlen(ptr->d_name)]='\0';
            //printf("qing");
            display(flag_param,filename[i]);
            //printf("hou");
        }
        closedir(dir);
        if(flag_param & PARAM_L ==0)  //没有l的时候打印一个换行符
        putchar('\n');
    }
}

int main(int argc ,char ** argv)
{
    int i=0,j=0,k=0,num=0;
    char path[_PC_PATH_MAX+1];
    char param[40];//保存命令行参数
    int flag_param=0;
    struct stat buf;

    for(i=0;i<argc;i++)
    {
        if(argv[i][0]=='-')
        {
            for(k=1;k<strlen(argv[i]);k++,j++)   //j是出现的参数总数
            param[j]=argv[i][k];  //保存命令行参数
        num++;  //保存 ’-‘ 的数量
        }
    }
    for(i=0;i<j;i++)
    {
        if(param[i]=='a')
        {
            flag_param|=PARAM_A;
        }else if(param[i]=='l')
        {
            flag_param|=PARAM_L;
        }else if(param[i]=='R')
        {
            flag_param|=PARAM_R;
        }else
        {
            printf("is a invaild param!\n");
            exit(1);
        }
    }
    int ff = 0 ;
    ff = flag_param;
    //printf("flag_param: %d\n",flag_param);
    //printf("%d  :flag_param: %d\n",ff,flag_param);
    param[j]='\0';
    if(num+1==argc)
    {
        strcpy(path,"./");  //没有参数的话默认为当前目录
        path[2]='\0';
        printf("%d  :flag_param: \n",ff);
        display_dir(flag_param,path);
        return 0;
    }
    i=1;
    do{
        //if(i==argc-1) return 0; //防止无参数时的段错误
        if(argv[i][0]=='-') 
        {
            i++;
            continue;
        }else
       {
            printf("%s\n",path);
            strcpy(path,argv[i]);
            if(stat(path,&buf)==-1)
            {
                my_err("stat",__LINE__);
            }
            if(S_ISDIR(buf.st_mode))
            {
                if(path[strlen(argv[i])-1]!='/')
                {
                    path[strlen(argv[i])]='/';
                    path[strlen(argv[i])+1]='\0';//保证字符串末尾为空零 方便进行字符串操作
                }else
                {
                    path[strlen(argv[i])]='\0';
                }
                //printf(":%d  :flag_param ok  : %d\n",ff,flag_param);
                display_dir(flag_param,path);
            }else
            {
                //printf("2    :%d  :flag_param ok  : %d\n",ff,flag_param);
                display(flag_param,path);//参数为一个文件
            }
            i++;
        }
    }while(i<argc);
    return 0;
}

链表写法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include "/usr/include/linux/limits.h"
#include <dirent.h>
#include <grp.h>
#include <pwd.h>
#include <error.h>
#include "List.h"
#define PARAM_NONE 0 //无参数
#define PARAM_A 1 //-a显示所有文件
#define PARAM_L 2 //-l一行只显示一个文件的信息
#define PARAM_R 4 //展示所有子目录中的文件
#define PARAM_r 8//逆序输出
#define PARAM_f 16//不排序
#define MAXROWLEN 150 //一行显示的最多字符数

int g_leave_len = MAXROWLEN;//一行剩余长度
int g_maxlen; //最长文件名字的长度
typedef struct 
{
    char name[NAME_MAX+1];
}name_t;//实体struct结构体
typedef struct name_node
{
    name_t data;
    struct name_node *prev;
    struct name_node *next;
}name_node_t;
typedef name_node_t *name_list_t;
void display_single(char *namei,struct stat *buf);
void AddToSortedList(name_list_t list,name_node_t *p)
{
    name_node_t *cur;
    if(!list) {List_AddTail(list,p);}
    else{
              cur = list->next;
              while(cur != list){
                  if(strcmp(p->data.name,cur->data.name) < 0) break;
                  cur = cur->next;
              }
              List_InsertBefore(cur,p);
    }
    return;
}
void  SortList(name_list_t list) {
    int flag = 1;
    name_list_t listLeft;
    List_Init(listLeft,name_node_t);
   if(!list)    flag = 0;
    if(flag){
   list->prev->next     =   NULL;//将循环链表最后一个节点断开
   listLeft     =   list->next;  //listleft指向第一个数据节点
   list->next   =     list->prev = list;//将list链表置为空
   while(listLeft != NULL){
       name_list_t p;
       p = listLeft;
       listLeft = listLeft->next;
       AddToSortedList(list,p);
   }}
}
//获取文件属性并且打印
void display_attribute(struct stat buf,char *name)
{
    char buf_time[32];
    struct passwd *psd;//文件所有者的用户名
    struct group *grp;//文件所有者所属组

    //获取并且打印文件类型
    if(S_ISLNK(buf.st_mode)) printf("l");
    else if(S_ISREG(buf.st_mode)) printf("-");
    else if(S_ISDIR(buf.st_mode)) printf("d");
    else if(S_ISCHR(buf.st_mode)) printf("c");
    else if(S_ISBLK(buf.st_mode)) printf("b");
    else if(S_ISFIFO(buf.st_mode)) printf("f");
    else if(S_ISSOCK(buf.st_mode)) printf("s");

    //打印文件所有者的权限
    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("-");

    //同组用户对文件的权限
    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("-");

    //其他用户
    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("-");

    //根据uid和gid获取文件所有者的用户名和组名
    psd = getpwuid(buf.st_uid);
    grp = getgrgid(buf.st_gid);
    printf("%4d ",(int)buf.st_nlink);//打印文件链接数
    printf("%-8s",psd->pw_name);
    printf("%-8s",grp->gr_name);

    printf("%6d",(int)buf.st_size);//打印文件大小
    strcpy(buf_time,ctime(&buf.st_mtime));
    buf_time[strlen(buf_time) - 1] = '\0';
    printf(" %s",buf_time); //打印文件的时间信息
    return ;
}
void my_err(const char *err_string,int line)
{
    fprintf(stderr,"line:%d",line);
    perror(err_string);
}

void display(int flag,char *pathname,name_list_t list)
{
    int i,j;
    struct stat buf;
    char name[NAME_MAX+1];

    //从路径中解析出文件名字
    for(i = 0,j = 0;i < (int) strlen(pathname);i++)
    {
        if(pathname[i] ==  '/')
        {
            j = 0;
            continue;
        }
        name[j++] = pathname[i];
    }
    name[j] = '\0';


    //用lstat而不是stat方便链接文件
    if(lstat(pathname,&buf) == -1) my_err("stat",__LINE__);

    switch(flag)
    {
        //没有参数
        case PARAM_NONE:
            if(name[0] != '.') display_single(name,&buf);
            break;

        case PARAM_A:
            display_single(name,&buf);
            break;

        case PARAM_L:
            if(name[0] != '.')
            {
                display_attribute(buf,name);
                printf(" %-s\n",name);
            }
            break;
        case PARAM_L + PARAM_A:
            //if(name[0] != '.')
            {
                display_attribute(buf,name);
                printf(" %-s\n",name);
            }
            break;
        case PARAM_R:
            if(name[0] != '.') 
                display_single(name,&buf);
            if(S_ISDIR(buf.st_mode))
            {
                //printf("yes\n");
                name_node_t *node =  (name_list_t)malloc(sizeof(name_node_t));
                strcpy(node->data.name,pathname);
                node->data.name[strlen(pathname)] = '/';
                node->data.name[strlen(pathname)+1] = '\0';
                List_AddTail(list,node);
            }
            break;
       case PARAM_R + PARAM_A:
            //if(name[0] != '.') 
                display_single(name,&buf);
            if(S_ISDIR(buf.st_mode) && name[0] != '.')
            {
                //printf("yes\n");
                name_node_t *node =  (name_list_t)malloc(sizeof(name_node_t));
                strcpy(node->data.name,pathname);
                node->data.name[strlen(pathname)] = '/';
                node->data.name[strlen(pathname)+1] = '\0';
                List_AddTail(list,node);
            }
            break;
       case PARAM_R + PARAM_L:
            if(name[0] != '.')
            {
                display_attribute(buf,name);
                printf(" %-s\n",name);
            }

            if(S_ISDIR(buf.st_mode))
            {
                //printf("yes\n");
                name_node_t *node =  (name_list_t)malloc(sizeof(name_node_t));
                strcpy(node->data.name,pathname);
                node->data.name[strlen(pathname)] = '/';
                node->data.name[strlen(pathname)+1] = '\0';
                List_AddTail(list,node);
            }
            break;
        case PARAM_r:
            if(name[0] != '.') display_single(name,&buf);
            break;
        case PARAM_f:
            if(name[0] != '.') display_single(name,&buf);
            break;



            
        default:
            break;
    }
}
void display_single(char *name,struct stat *buf)
{
    int i,len;

    //如果本行不足以打印一个文件名则换行
    if(g_leave_len < g_maxlen)
    {
        printf("\n");
        g_leave_len = MAXROWLEN;
    }

    len = strlen(name);
    len = g_maxlen - len;
    if(S_ISDIR(buf->st_mode))
    printf("\033[41;36m%-s\033[0m",name);
    else
    printf("%-s",name);
    for(i = 0;i<len;i++)    printf(" ");
    printf("  ");
    //2表示空两格
    g_leave_len -= (g_maxlen+2);
}
void display_dir(int flag_param,char *path)
{
    g_maxlen = -1;
    name_list_t list;
    name_list_t cur_list;
    List_Init(cur_list,name_node_t);
    List_Init(list,name_node_t);
    DIR *dir;
    struct dirent *ptr;
    int count = 0;
    /* char file_names[256][PATH_MAX+1],temp[PATH_MAX+1]; *///此处改为在堆区开辟空间


    //获取该目录下目录总数和最长文件名字
    dir = opendir(path);
    if(dir == NULL)
    {
        my_err("openir",__LINE__);
    }
    while((ptr = readdir(dir)) != NULL)
    {
        if((flag_param & 1) && ptr->d_name[0] == '.') count++;
        else if(ptr->d_name[0] != '.') count++;
        if(g_maxlen < (int)strlen(ptr->d_name))
            g_maxlen = strlen(ptr->d_name);
    }
    closedir(dir);
    
    printf("文件总数:%d\n",count);
   /* if(count > 256)//有什么用处  未知 */
   /* { */
   /*     my_err("该目录下的文件太多!",__LINE__); */
   /* } */

    int i,j,len = strlen(path);
   //获取该目录下的所有文件名字
   dir = opendir(path);
   for(i = 0;i < count ;i++)
   {
       ptr = readdir(dir);
       if(!(flag_param&1) && ptr->d_name[0] == '.')
       {
           i--;
           continue;
       }
       if(ptr == NULL) my_err("readdir",__LINE__);
        else{
        name_node_t *node = (name_list_t)malloc(sizeof(name_node_t));
       strncpy(node->data.name,path,len);
       node->data.name[len] = '\0';
       strcat(node->data.name,ptr->d_name);
       node->data.name[len + (int)strlen(ptr->d_name)] = '\0';
       List_AddTail(cur_list,node);
    }
   }

   //使用冒泡法对文件名进行排序
   /* for(i = 0;i<count - 1;i++) */
   /*     for(j = i+1;j<count - 1;j++) */
   /*     { */
   /*         if(strcmp(file_names[i],file_names[j]) > 0 ) */
   /*         { */
   /*             strcpy(temp,file_names[i]); */
   /*             strcpy(file_names[i],file_names[j]); */
   /*             strcpy(file_names[j],temp); */
   /*         } */
   /*     } */

   /* for(i = 0;i<count;i++)//单个打印文件 */
       /* display(flag_param,file_names[i],list,i,count-1); */
   if(!(flag_param&16))
    SortList(cur_list);
    name_list_t p;
    if((flag_param&8))
    List_ForEach2(cur_list,p)
    {
        display(flag_param,p->data.name,list);
    }
    else 
    List_ForEach(cur_list,p)
    {
        display(flag_param,p->data.name,list);
    }
   closedir(dir);
    /* if(cur == count) */
            {
                //printf("yes\n");
                name_list_t p;
                printf("\n");
                List_ForEach(list,p)
                {
                    printf("\n%s\n",p->data.name);
                    display_dir(flag_param,p->data.name);
                }
            }
        

   //如果命令中没有-l 打印一个换行符
   if((flag_param & PARAM_L) == 0)  printf("\n");
   return ;
}
int main(int argc,char ** argv)
{
    int i,j,k,num;
    char path[PATH_MAX+1];
    char param[32]; //保存命令行参数,目标文件和命令行不在此列。
    int flag_param = PARAM_NONE;//参数种类即是否有-a -l选项
    struct stat buf;
    
    //命令行参数解析,分析-l -a -al -la 选项
    j = 0;num = 0;
    for(i = 0;i<argc;i++)
    {
        if(argv[i][0] == '-')
        {
            for(k = 1;k<(int)strlen(argv[i]);k++,j++)
            {
                param[j] = argv[i][k]; //获取-后面的参数保存到数组param中
            }
        num++; //保存-的个数
        }
    }

    //只支持参数-a -l 其他报错
    for(i = 0;i<j;i++)
    {
        if(param[i] == 'a')    flag_param |= PARAM_A;
        
        else if(param[i] == 'l')     flag_param |= PARAM_L; 
   
        else if(param[i] == 'R')     flag_param |= PARAM_R;
        
        else if(param[i] == 'r')     flag_param |= PARAM_r;
        
        else if(param[i] == 'f')     flag_param |= PARAM_f; 
        else
        {
            printf("my_ls:invalid option -%c\n",param[i]);
            exit(1);
        }
    }
    param[j] = '\0';

    //如果没有输入文件名就显示当前目录
    if(num + 1 == argc)
    {
        strcpy(path,"./");
        path[2] = '\0';
        display_dir(flag_param,path);
        return 0;
    }
    
    i = 1;
    do
    {
        //如果不是目标文件或目录,解析下一个命令参数
        if(argv[i][0] == '-')
        {
            i++;
            continue;
        }
        else
        {
            strcpy(path,argv[i]);
            //如果目标文件或者目录不存在,报错退出程序
            if(stat(path,&buf) == -1)
            {
                my_err("stat",__LINE__);
            }


            if(S_ISDIR(buf.st_mode))
            {//grgv[i]是一个目录
            //如果目录最后一个字符不是/ , 就加上/
            if(path[(int)strlen(argv[i])-1] != '/')
            {
                path[(int)strlen(argv[i])] = '/';
                path[(int)strlen(argv[i])+1] = '\0';
            }
            else path[(int)strlen(argv[i])] = '\0';
            display_dir(flag_param,path);
            i++;
            
            }
        }
    }while(i<argc);
    return 0;
}

上文中使用的list.h

#ifndef LIST_H_
#define LIST_H_
#include <stdlib.h>
#include <assert.h>



/*��ʼ������list������Ϊ��ͷ����˫��ѭ������*/
#define List_Init(list,list_node_t) {					\
		list=(list_node_t*)malloc(sizeof(list_node_t)); \
		(list)->next=(list)->prev=list;					\
	}

//�ͷ�����list���������ݽ�㡣list Ϊ����ͷָ�룬list_node_tΪ����������
#define List_Free(list,list_node_t) {			\
		assert(NULL!=list);						\
		list_node_t *tmpPtr;					\
		(list)->prev->next=NULL; 				\
		while(NULL!=(tmpPtr=(list)->next)){ 	\
			(list)->next=tmpPtr->next;			\
			free(tmpPtr);						\
		}										\
		(list)->next=(list)->prev=list;			\
	}

//��������list���ͷ��������ݽ�㼰ͷ��㡣 listΪ����ͷָ�룬tmpPtrΪ��������ʱָ�����
#define List_Destroy(list,list_node_t) {		\
		assert(NULL!=list);						\
		List_Free(list, list_node_t);			\
		free(list);								\
		(list)=NULL;							\
	}

//����ͷ�巨��listΪͷָ�룬newΪ�½ڵ�
#define List_AddHead(list,newNode) {			\
		(newNode)->next=(list)->next;		 	\
		(list)->next->prev=newNode;			 	\
		(newNode)->prev=(list);				 	\
		(list)->next=newNode;				 	\
	}

//����β�巨��listΪͷָ�룬newΪ�½ڵ�
#define List_AddTail(list,newNode) {			\
		(newNode)->prev=(list)->prev; 		 	\
		(list)->prev->next=newNode;			 	\
		(newNode)->next=list;				 	\
		(list)->prev=newNode;				 	\
	}

//���½ڵ�newNode���뵽node֮ǰ
#define List_InsertBefore(node,newNode) {		\
		(newNode)->prev=(node)->prev; 		 	\
		(newNode)->next=node;			 		\
		(newNode)->prev->next=newNode;			\
		(newNode)->next->prev=newNode;			\
	}

//���½ڵ�newNode���뵽node֮��
#define List_InsertAfter(node, newNode) {		\
		(newNode)->next=node->next;			 	\
		(newNode)->prev=node; 				 	\
		(newNode)->next->prev=newNode;			\
		(newNode)->prev->next=newNode;			\
	}

//�ж������Ƿ�Ϊ�գ�listΪͷָ��
#define List_IsEmpty(list)  ((list != NULL)	\
	&& ((list)->next == list)				\
	&& (list == (list)->prev))

//��ɾ��������node��
#define List_DelNode(node) {\
			assert(NULL!=node && node!=(node)->next && node!=(node)->prev);				\
			(node)->prev->next=(node)->next; 	\
			(node)->next->prev=(node)->prev;	\
	}

//��������ɾ�����ͷŽ��node
#define List_FreeNode(node) {	\
		List_DelNode(node);		\
		free(node);				\
	}


//ʹ��ָ��curPos���α�������list
#define List_ForEach(list, curPos) 		\
	 for (   curPos = (list)->next;  	\
		  	  	  curPos != list;       \
		  	  	  curPos=curPos->next	\
	    )
#define List_ForEach2(list, curPos)\
	 for (   curPos = (list)->prev;  	\
		  	  	  curPos != list;       \
		  	  	  curPos=curPos->prev	\
	    )

/*
void AddToSortedList(name_list_t list,name_node_t *p)
{
    name_node_t *cur;
    if(!list) {List_AddTail(list,p);}
    else{
              cur = list->next;
              while(cur != list){
                  if(p->data.age < cur->data.age) break;
                  cur = cur->next;
              }
              List_InsertBefore(cur,p);
    }
    return;
}
void  SortByNum(name_list_t list) {
    int flag = 1;
    name_list_t listLeft;
    List_Init(listLeft,name_node_t);
   if(!list)    flag = 0;
    if(flag){
   list->prev->next     =   NULL;//将循环链表最后一个节点断开
   listLeft     =   list->next;  //listleft指向第一个数据节点
   list->next   =     list->prev = list;//将list链表置为空
   while(listLeft != NULL){
       name_list_t p;
       p = listLeft;
       listLeft = listLeft->next;
       AddToSortedList(list,p);
   }}
}
*/
#endif /* LIST_H_ */
posted @ 2022-07-02 13:18  李兆龙的博客  阅读(125)  评论(0编辑  收藏  举报