简单实现ls

简单实现ls


需要注意的点

1.若你打算用字符数组存储文件名,因为栈的大小是有限的,很容易造成栈溢出。所以建议用动态内存分配空间或修改栈的大小。本文使用的是动态内存分配,若想修改栈的大小请参考下面的博文。
Linux修改栈空间的大小
2.及时输出错误信息可以帮助你快速找出错误。
3.遍历根目录时有可能出现权限不足的情况,可用root身份执行。
4.若opendir失败请检查文件名是否正确。
5.用lstat查看链接的属性,否则将出现错误。

二、代码

1.用于输出错误的函数

代码如下(示例):
第一行代码输出错误位置
第二行代码用于输出错误信息

void my_error(const char *error_string, int line)
{
    fprintf(stderr, "line:%d",line);
    perror(error_string);
    
}

2.用于打开目录并读取所有文件名并存在动态数组中

代码如下(示例):
遍历两遍目录,第一遍用于获取文件数和最长文件文件名。然后申请合适的空间,在第二遍时存储文件名。

void work_dir(char *path,int flag)
{
    
    DIR *dir;
    int num=0;
    int i=0;
    struct dirent*ptr;
    if ((dir=opendir(path))==NULL) //若打开失败则会返回
    {
        my_error("opendir",__LINE__);
        return;
    }
    while ((ptr=readdir(dir))!=NULL)	//持续读取文件直到无文件可读时返回NULL
    {
        num++;							//记录文件个数
        if ((strlen(ptr->d_name)>max_long))
        {
            max_long=strlen(ptr->d_name);//记录最长的文件名
        }
    }
    closedir(dir);						//关闭目录
    if ((dir=opendir(path))==NULL)		//再次打开目录
    {
        my_error("opendir",__LINE__);
        return;
    }
    char *filenames[num];
    for (i = 0;i < num;i++)				//申请空间
    {
        filenames[i] = (char*)malloc(sizeof(char) * PATH_MAX);
        if (filenames[i]==NULL)
        my_error("malloc",__LINE__);
    }
    
    int len=strlen(path);
    if (filenames==NULL)
    {
        my_error("malloc",__LINE__);
    }
    for (i=0;i<num;i++)
    {   if ((ptr=readdir(dir))==NULL)
        {
            my_error("opendir",__LINE__);
            return;
        }
        strncpy(filenames[i],path,len);
        filenames[i][len]='\0';
        strcat(filenames[i],ptr->d_name);
        
    }
    closedir(dir);
    printf("%s:\n",path);      //输出目录名

        int a[num];
        for (i=0;i<num;i++)
        { 
            a[i]=i;
        } 
        //以下为冒泡排序,用于根据文件名首字母对其进行排序,这里采用了只对其序号的顺序进行改变的方法。
        int j,t; 

        for(j=0;j<num-1;j++) 

            {for(i=0;i<num-1-j;i++) 

             {   if(strcmp(filenames[a[i]],filenames[a[i+1]])>=0)

                { 

                t=a[i]; 

                a[i]=a[i+1]; 

                a[i+1]=t; 

                }

             }
            }

    space=80;
    for (i=0;i<num;i++)
    {
        display_type(filenames[a[i]],flag);	//输出
        
    }
    
    printf("\n");
    if (flag==4|| flag==5||flag==7||flag==6)
    {
        display_R(flag,filenames,num);		//若有——R命令则进行
    }
}

3.实现-R命令

代码如下(示例):

void display_R(int flag,char *pastfile[],int num)
{
    
    flag -= 4;
    int i;
    struct stat buf;
    char a[PATH_MAX];
    int k,j=0;
    char *temple=(char*)malloc(sizeof(char)* PATH_MAX);
    for (i=0;i<num;i++)
    {
        
        int l=strlen(pastfile[i]);
        strcpy(temple, pastfile[i]);
        temple[l] = '\0';
        for (k = 0, j = 0; k < strlen(pastfile[i]); k++)
            {
                if (pastfile[i][k] == '/')
                {
                    j = 0;
                    continue;
                }
                a[j++] = pastfile[i][k];
            }
            a[j] = '\0';
        if (strcmp(a,".")==0||strcmp(a,"..")==0) //若是当前目录或父目录则跳过
        {
            continue;
        }
        if (lstat(pastfile[i], &buf) == -1) //获取文件信息
        {
            printf("%s\n",pastfile[i]);
            my_error("lstat",__LINE__);
            continue;
        }
        if (S_ISDIR(buf.st_mode))  //判断是否是目录
        {
            
            if (temple[l-1] != '/')
            {
                strcat(temple,"/");	//若是目录且不为/结尾则补上
            }
            if (flag == 0)	//是否屏蔽隐藏文件
            {
                if (a[0]!= '.')
                {
                    work_dir(temple,flag+4);
                }
            }
            else if (flag == 1)
            {
                work_dir(temple,flag+4);
            }
            else if (flag == 2)
            {
                if (a[0] != '.')
                {
                    work_dir(temple,flag+4);
                }
            }
            else if (flag == 3)
            {
                work_dir(temple,flag+4);
            }
        }
        free(pastfile[i]);	每遍历一次就及时释放掉遍历过的内存
    }
    free(temple);	释放内存
}

4.完整代码

代码如下(示例):

//只支持-l -a -R
#include<stdio.h>
#include <string.h>
#include<sys/stat.h>
#include <unistd.h>
#include <linux/limits.h>
#include<stdlib.h>
#include<sys/types.h>
#include <signal.h>
#include<errno.h>
#include<time.h>
#include <grp.h>
#include <dirent.h>
#include <pwd.h>
#define MAX_SIZE 80;        //最大的行宽
int space=MAX_SIZE;         //剩余空间
int max_long=0;        //每个目录下最长的文件名
void work_dir(char *path,int flag);
void my_error(const char *error_string, int line);
void simple_play(char *name);
void all_play(char *name,struct stat buf);
void display_R(int flag,char *pastfile[],int num);
void display_type(char *name,int flag);

//颜色选择
#define CLOSE printf("\033[0m"); //关闭彩色字体
#define RED printf("\033[31m"); //红色字体
#define GREEN printf("\033[36m");//绿色字体
#define YELLOW printf("\033[33m");//黄色字体
#define BLUE printf("\033[34m");//蓝色字体
#define PURPLE printf("\033[35m");//紫色
#define WHITE printf("\033[37m");//白色
#define DD printf("\033[34m"); //浅绿色

void colorprint(struct stat buf)
{
    if (S_ISLNK(buf.st_mode))
    {
        
        RED
    }
    else if (S_ISREG(buf.st_mode))
    {
        GREEN
        
    }
    else if (S_ISDIR(buf.st_mode))
    {
        YELLOW
    }
    else if (S_ISCHR(buf.st_mode))
    {
        BLUE
    }
    else if (S_ISBLK(buf.st_mode))
    {
        WHITE
    }
    else if (S_ISFIFO(buf.st_mode))
    {
        PURPLE
    }
    else if (S_ISSOCK(buf.st_mode))
    {
        DD
    }
}
void my_error(const char *error_string, int line)
{
    fprintf(stderr, "line:%d",line);
    perror(error_string);
    
}
void simple_play(char *name) //无参数只输出名字
{
    printf("%s",name);
    int len=strlen(name);
    int i=0;
    for (i=0;i<max_long-len;i++)
    {
        printf(" ");
    }
    printf("  ");
    space=space-max_long-2;
    
    if (max_long>space)
    {
        printf("\n");
        space=80;
    }
}

void all_play(char *name,struct stat buf)
{
    struct passwd *p;
    struct group *g;
    GREEN
    g = getgrgid(buf.st_gid);
    p = getpwuid(buf.st_uid);
    if (g==NULL||p==NULL)
    {   printf("无法打开文件\n");
        perror("getpwuid");
        return;
    }
    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("-");
    printf(" ");
    printf("%ld", buf.st_nlink);
    printf(" ");
    printf("%-5s", p->pw_name);
    printf("%-5s", g->gr_name);
    printf("%6ld", buf.st_size);
    printf(" ");
    int size = strlen(ctime(&buf.st_ctime));
    char timering[size + 1];
    strcpy(timering, ctime(&buf.st_ctime));
    timering[size - 1] = '\0';
    printf("%s", timering);
    printf(" ");
    CLOSE
    colorprint(buf);
    printf("%s", name);
    CLOSE
    printf("\n");
}
void display_R(int flag,char *pastfile[],int num)
{
    
    flag -= 4;
    int i;
    struct stat buf;
    char a[PATH_MAX];
    int k,j=0;
    char *temple=(char*)malloc(sizeof(char)* PATH_MAX);
    for (i=0;i<num;i++)
    {
        
        int l=strlen(pastfile[i]);
        strcpy(temple, pastfile[i]);
        temple[l] = '\0';
        for (k = 0, j = 0; k < strlen(pastfile[i]); k++)
            {
                if (pastfile[i][k] == '/')
                {
                    j = 0;
                    continue;
                }
                a[j++] = pastfile[i][k];
            }
            a[j] = '\0';
        if (strcmp(a,".")==0||strcmp(a,"..")==0)
        {
            continue;
        }
        if (lstat(pastfile[i], &buf) == -1)
        {
            printf("%s\n",pastfile[i]);
            my_error("lstat",__LINE__);
            continue;
        }
        if (S_ISDIR(buf.st_mode))
        {
            
            if (temple[l-1] != '/')
            {
                strcat(temple,"/");
            }
            if (flag == 0)
            {
                if (a[0]!= '.')
                {
                    work_dir(temple,flag+4);
                }
            }
            else if (flag == 1)
            {
                work_dir(temple,flag+4);
            }
            else if (flag == 2)
            {
                if (a[0] != '.')
                {
                    work_dir(temple,flag+4);
                }
            }
            else if (flag == 3)
            {
                work_dir(temple,flag+4);
            }
        }
        free(pastfile[i]);
    }
    free(temple);
}
void display_type(char *name,int flag)
{   
    int temple=flag;
    if (flag==4|| flag==5||flag==7||flag==6)
    {
        flag-=4;
    }
    int i = 0, j = 0;
    char a[PATH_MAX];
    struct stat buf;

    for (i = 0, j = 0; i < strlen(name); i++)
    {
        if (name[i] == '/')
        {
            j = 0;
            continue;
        }
        a[j++] = name[i];
    }
    a[j] = '\0';

    if (lstat(name, &buf) == -1)
    {
        printf("%s",name);
        my_error("lstat",__LINE__);
        return;
    }

    if (flag == 0)
    {
        if (a[0] != '.')
        {
            colorprint(buf);
            simple_play(a);
            CLOSE
        }
    }
    else if (flag == 1)
    {
        colorprint(buf);
        simple_play(a);
        CLOSE
    }
    else if (flag == 2)
    {
        if (a[0] != '.')
        {
            
            all_play(a,buf);
            
        }
    }
    else if (flag == 3)
    {
        
        all_play(a,buf);
        
    }
    
}

void work_dir(char *path,int flag)
{
    
    DIR *dir;
    int num=0;
    int i=0;
    struct dirent*ptr;
    if ((dir=opendir(path))==NULL)
    {
        my_error("opendir",__LINE__);
        return;
    }
    while ((ptr=readdir(dir))!=NULL)
    {
        num++;
        if ((strlen(ptr->d_name)>max_long))
        {
            max_long=strlen(ptr->d_name);
        }
    }
    closedir(dir);
    if ((dir=opendir(path))==NULL)
    {
        my_error("opendir",__LINE__);
        return;
    }
    char *filenames[num];
    for (i = 0;i < num;i++)
    {
        filenames[i] = (char*)malloc(sizeof(char) * PATH_MAX);
        if (filenames[i]==NULL)
        my_error("malloc",__LINE__);
    }
    
    int len=strlen(path);
    if (filenames==NULL)
    {
        my_error("malloc",__LINE__);
    }
    for (i=0;i<num;i++)
    {   if ((ptr=readdir(dir))==NULL)
        {
            my_error("opendir",__LINE__);
            return;
        }
        strncpy(filenames[i],path,len);
        filenames[i][len]='\0';
        strcat(filenames[i],ptr->d_name);
        
    }
    closedir(dir);
    printf("%s:\n",path);





        space =MAX_SIZE;
        int a[num];
        for (i=0;i<num;i++)
        { 
            a[i]=i;
        } 
        int j,t; 

        for(j=0;j<num-1;j++) 

            {for(i=0;i<num-1-j;i++) 

             {   if(strcmp(filenames[a[i]],filenames[a[i+1]])>=0)

                { 

                t=a[i]; 

                a[i]=a[i+1]; 

                a[i+1]=t; 

                }

             }
            }

    for (i=0;i<num;i++)
    {
        display_type(filenames[a[i]],flag);
        
    }
    
    printf("\n");
    if (flag==4|| flag==5||flag==7||flag==6)
    {
        display_R(flag,filenames,num);
    }
}

int main(int argc, char **argv)
{
   // signal(SIGINT, SIG_IGN);
    char argustr[100];
    int count_arguments=0;
    struct stat buf;
    int i=1;
    for (i=1;i<argc;i++)
    {   
        if (argv[i][0]=='-')
        {
        count_arguments++;
        strcat(argustr, argv[i]);
        }
        
    }
    int flag=0;
//获取ls的参数,a=1,l=2,R=4;
    int l=strlen(argustr);
    int judge_a=0,judge_l=0,judge_R=0;
    for (i=0;i<l;i++)
    {
        if (argustr[i]=='-')
        {
            continue;
        }
        else if (argustr[i]=='a'&&judge_a==0)
        {
             flag++;
             judge_a=1;
        }
        else if (argustr[i]=='l'&&judge_l==0)
        {
             flag=flag+2;
             judge_l=1;
        }else if (argustr[i]=='R'&&judge_R==0)
        {
             flag=flag+4;
             judge_R=1;
        }
        else
        {
            printf("arguments don't support");
            exit(0);           
        }
    }
    char path[PATH_MAX];       //无参数就作用于当前目录。
    if (argc==(count_arguments+1))
    {
        strcpy(path,"./");
        path[2]='\0';
        work_dir(path,flag);
    }
    for (i=1;i<argc;i++)
    {
        if (argv[i][0]=='-')
        {
            continue;
        }
        if (lstat(argv[i],&buf)==-1)
        {
            my_error("lstat",__LINE__);

            continue;
        }
        if (S_ISDIR(buf.st_mode)) //是目录就先处理后遍历文件
                {
            int l=strlen(argv[i]);
            if (argv[i][l-1]!='/')
            {
                strcpy(path,argv[i]);
                path[l]='/';
                path[l+1]='\0';
            }
            else
            {
                strcpy(path,argv[i]);
                path[l]='\0';
            }
            work_dir(path,flag);
        }
        else //是文件时直接打印
        {
            display_type(path,flag);
        }
    }
        
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值