To achieve the realization of improved ls ls and the ls

Ls to achieve the realization and improvement of ls

Reference pseudo-code for the function ls submit the compiled code, the results shots, cloud code Code link.

Open the file directory

For the directory file

Read directory entry

Displays the file name

Close the file directory file

ls implementation code:

#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 PARAM_NONE 0 //无参数
#define PARAM_A    1 //-a
#define PARAM_L    2 //-l
#define MAXROWLEN  80 //一行最多显示的字符数

int g_leave_len = MAXROWLEN; //一行是剩余长度,用于输出对齐
int g_maxlen;                //存放某目录下最长文件名的长度

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

//打印单个文件,且没有-l参数
void display_single(char *name)
{
    int i,len;
    //如果本行不足以打印一个文件名则换行
    if(g_leave_len < g_maxlen)
    {
        printf("\n");
        g_leave_len = MAXROWLEN;
    }
    
    len = strlen(name);
    len = g_maxlen - len;
    
    printf("%-s",name);

    for(i=0;i<len;i++)
    {
        printf(" ");
    }
    printf(" ");

    g_leave_len = g_leave_len - g_maxlen - 2;

}

/*获取文件属性并打印*/
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("1");
    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("  ");
    
    //根据uid和gid获取文件所有者的用户名于组名
    psd = getpwuid(buf.st_uid);
    grp = getgrgid(buf.st_gid);
    printf("%4d",buf.st_nlink);
    printf("%-8s",psd->pw_name);
    printf("%-9s",grp->gr_name);
    
    printf("%6d",buf.st_size);
    strcpy(buf_time, ctime(&buf.st_mtime));//将格林位置时间转化成正常时间格式
    buf_time[strlen(buf_time) - 1] = 0;
    printf(" %s",buf_time);
}

//根据flag参数显示文件内容,调用display_single或者display_attribute
void display(int flag,char *pathname)
{
    int i,j;
    struct stat buf;
    char name[NAME_MAX + 1];

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

    if(lstat(pathname,&buf) == -1)
    {
        my_error("stat",__LINE__);
    }
    
    if(flag == PARAM_NONE)
    {
        if(name[0] != '.')//不显示隐藏文件
        {
            display_single(name);
        }
    }
    else if(flag == PARAM_A)
    {
        display_single(name);
    }
    else if(flag == PARAM_L)
    {
        if(name[0] != '.')
        {
            display_attribute(buf,name);
            printf(" %-s\n",name);
        }
    }
    else if(flag == (PARAM_A | PARAM_L))
    {
        display_attribute(buf,name);
        printf(" %-s\n",name);
    }

}

void display_dir(int flag_param,const char *path)
{
    DIR* dir;
    struct dirent* dirent;
    char filenames[256][PATH_MAX+1],temp[PATH_MAX+1];
    int count = 0;//总共有多少个文件

    if((dir = opendir(path)) == NULL)
    {
        my_error("opendir",__LINE__);
    }
    
    //获取文件总数和最长文件名
    while((dirent = readdir(dir)) != NULL)
    {
        if(g_maxlen < strlen(dirent->d_name))
            g_maxlen = strlen(dirent->d_name);
        count++;
    }
    closedir(dir);
    
    if(count>256)
        my_error("文件太多超过了256个",__LINE__);
    
    int i,j,len = strlen(path);
    //获取目录下所有的文件名
    dir = opendir(path);
    for(i=0;i<count;i++)
    {
        dirent = readdir(dir);
        if(dirent == NULL)
        {
            my_error("readdir",__LINE__);    
        }
        strncpy(filenames[i],path,len);
        filenames[i][len] = 0;
        strcat(filenames[i],dirent->d_name);
        filenames[i][len+strlen(dirent->d_name)] = 0;
    }

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

    for(i=0;i<count;i++)
        display(flag_param,filenames[i]);
    closedir(dir);
    
    //没有-l的话打印一个换行符
    if((flag_param & PARAM_L) == 0)
        printf("\n");
}

int main(int argc, char **argv)
{
    int i,j,k;
    int num;//记录-的个数
    char path[PATH_MAX + 1];
    char param[32]; // 保存命令行参数
    int  flag_param = PARAM_NONE;
    struct stat buf;
    
    j = 0;
    num = 0;
    for(i=1;i<argc;i++)
    {
        if(argv[i][0] == '-')
        {
            for(k=1;k<strlen(argv[i]);k++)
            {
                param[j] = argv[i][k];
                j++;
            }
            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
        {
            printf("错误的参数:%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;
    for(i=1;i<argc;i++)
    {
        if(argv[i][0] != '-')
        {
            strcpy(path,argv[i]);
            if(stat(path,&buf) == -1)
                my_error("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; 
            
                display_dir(flag_param,path);
            }
            else
            {
                display(flag_param,path);
            }
        }
    }

    return 0;     
}

Build an executable file

-L -a test

Referring to the drawings, an improved realization of your ls. Submit code run shot and cloud code link.


Implementation code:

#include <stdio.h>  
#include <sys/types.h>  
#include <dirent.h>  
#include <sys/stat.h>  
#include <pwd.h>  
#include <grp.h>  
#include <unistd.h>  
#include <string.h>  
#define LS_NONE 0  
#define LS_L 101  
#define LS_R 102  
#define LS_D 103  
#define LS_I 104  
#define LS_A 200  
#define LS_AL (LS_A+LS_L)  
#define LS_AI (LS_A+LS_I)  
      
// 展示单个文件的详细信息  
void show_file_info(char* filename, struct stat* info_p)  
{  
    char* uid_to_name(), *ctime(), *gid_to_name(), *filemode();  
    void mode_to_letters();  
    char modestr[11];  
    mode_to_letters(info_p->st_mode, modestr);  
    printf("%s", modestr);  
    printf(" %4d", (int) info_p->st_nlink);  
    printf(" %-8s", uid_to_name(info_p->st_uid));  
    printf(" %-8s", gid_to_name(info_p->st_gid));  
    printf(" %8ld", (long) info_p->st_size);  
    printf(" %.12s", 4 + ctime(&info_p->st_mtime));  
    printf(" %s\n", filename);  
}  
      
void mode_to_letters(int mode, char str[])  
    {  
    strcpy(str, "----------");  
    if (S_ISDIR(mode))  
    {  
        str[0] = 'd';  
    }  
    if (S_ISCHR(mode))  
    {  
        str[0] = 'c';  
    }  
    if (S_ISBLK(mode))  
    {  
        str[0] = 'b';  
    }  
    if ((mode & S_IRUSR))  
    {  
        str[1] = 'r';  
    }  
    if ((mode & S_IWUSR))  
    {  
        str[2] = 'w';  
    }  
    if ((mode & S_IXUSR))  
    {  
        str[3] = 'x';  
    }  
    if ((mode & S_IRGRP))  
    {  
        str[4] = 'r';  
    }  
    if ((mode & S_IWGRP))  
    {  
        str[5] = 'w';  
    }  
    if ((mode & S_IXGRP))  
    {  
        str[6] = 'x';  
    }  
    if ((mode & S_IROTH))  
    {  
        str[7] = 'r';  
    }  
    if ((mode & S_IWOTH))  
    {  
        str[8] = 'w';  
    }  
    if ((mode & S_IXOTH))  
    {  
        str[9] = 'x';  
    } 
}  
      
char* uid_to_name(uid_t uid)  
{  
    struct passwd* getpwuid(),* pw_ptr;  
    static char numstr[10];  
      
    if((pw_ptr = getpwuid(uid)) == NULL)  
    {  
        sprintf(numstr,"%d",uid);  
      
        return numstr;  
    }  
    else  
    {  
        return pw_ptr->pw_name;  
    }  
}  
      
char* gid_to_name(gid_t gid)  
{  
    struct group* getgrgid(),* grp_ptr;  
    static char numstr[10];  
      
    if(( grp_ptr = getgrgid(gid)) == NULL)  
    {  
        sprintf(numstr,"%d",gid);  
        return numstr;  
    }  
    else  
    {  
        return grp_ptr->gr_name;  
    }  
}  
    
void do_ls(char dirname[],int mode)  
{  
    DIR* dir_ptr;  
    struct dirent* direntp;  
      
    if ((dir_ptr = opendir(dirname)) == NULL)  
    {  
        fprintf(stderr, "ls2: cannot open %s \n", dirname);  
    }  
    else  
    {  
        if(mode==LS_D)  
        {  
            printf("%s\n", dirname);  
        }  
        else  
        {  
            char dirs[20][100];  
            int dir_count = 0;  
                  
            while ((direntp = readdir(dir_ptr)) != NULL)  
            {  
      
                if(mode < 200 && direntp->d_name[0]=='.')  
                {  
                    continue;  
                } 
                char complete_d_name[200];  // 文件的完整路径  
                strcpy (complete_d_name,dirname);  
                strcat (complete_d_name,"/");  
                strcat (complete_d_name,direntp->d_name);  
                      
                struct stat info;  
                if (stat(complete_d_name, &info) == -1)  
                {  
                    perror(complete_d_name);  
                }  
                else  
                {  
                    if(mode == LS_L||mode == LS_AL)  
                    {  
                        show_file_info(direntp->d_name, &info);  
                    }  
                    else if(mode == LS_A||mode == LS_NONE||mode == LS_I||mode == LS_AI)  
                    {  
                        if(mode == LS_I||mode == LS_AI)  
                        {  
                            printf("%llu ", direntp->d_ino);  
                        }  
      
                        printf("%s\n", direntp->d_name);  
                    }  
                    else if(mode == LS_R)  
                    {  
      
                        if(S_ISDIR(info.st_mode))  
                        {  
                            printf("%s\n", direntp->d_name);  
                            strcpy (dirs[dir_count],complete_d_name);  
                            dir_count++;  
                        }  
                        else  
                        {  
                            printf("%s\n", direntp->d_name);  
                        }  
                    } 
                }  
            }  
            if(mode == LS_R)  
            {  
                int i=0;  
                printf("\n");  
                for(;i<dir_count;i++){  
                printf("%s:\n", dirs[i]);  
                do_ls(dirs[i],LS_R);  
                printf("\n");  
                }  
            }  
        }  
        closedir(dir_ptr);  
    }  
}  
      
// 解析一个单词参数,如-l,-i  
int analyzeParam(char* input){  
    if(strlen(input)==2)  
    {  
        if(input[1]=='l') return LS_L;  
        if(input[1]=='a') return LS_A;  
        if(input[1]=='d') return LS_D;  
        if(input[1]=='R') return LS_R;  
        if(input[1]=='i') return LS_I;  
    }  
    else if(strlen(input)==3)  
    {  
        if(input[1]=='a'&& input[2]=='l') return LS_AL;  
        if(input[1]=='a'&& input[2]=='i') return LS_AI;  
    }  
    return -1;  
}  
      
int main(int ac,char* av[])  
{  
    if(ac == 1)  
    {  
        do_ls(".",LS_NONE);  
    }  
    else  
    {  
        int mode = LS_NONE; // 默认为无参数ls  
        int have_file_param = 0; // 是否有输入文件参数  
        while(ac>1)  
        {  
            ac--;  
            av++;  
            int calMode = analyzeParam(*av);  
            if(calMode!=-1)  
            {  
                mode+=calMode;  
            }  
            else  
            {  
                have_file_param = 1;  
                do  
                {  
                    printf("%s:\n", *av);  
                    do_ls(*av,mode);  
                    printf("\n");  
                    ac--;  
                    av++;  
                }while(ac>=1);  
            }  
        }  
        if (!have_file_param)  
        {  
            do_ls(".",mode);  
        }  
    }       
}

makels improve test:

Code link to submit cloud chart:

Cloud link code

Guess you like

Origin www.cnblogs.com/ldc175206/p/12114475.html
Recommended