Implementation of LS command

Source: Internet
Author: User

Under Linux, we use the most command should be LS, then, have you ever wondered how this command is implemented? In fact, after understanding the UNIX environment of the relevant interface, it is not difficult ~


Goal:

You can use LS to list the directory's abbreviated information, ls-l lists the details of the directory. The information under this working directory is listed by default and can be specified by parameters, and multiple directory information can be listed at the same time.


Realize:

Implementation of the way there are very many, as long as the good style can be done on the line, I will briefly talk about their own ideas.

1. Use the Is_detail variable to record whether the file details are listed, Initpath indicates the directory path that will be read.

2. If the user does not specify a directory, the direct setting of the path is the current working directory, after obtaining all the files in the directory, sorting, followed by a brief output or verbose output. End the program.

3. When the user has provided the directory parameters, determine whether to perform verbose output, set the Is_detail variable.

4. For each user to specify the directory parameters, loop: Get all the filenames under the directory, sort, print the information according to Is_detail.

The idea is so simple that you just have to deal with the details of each module.


The main auxiliary functions are:

GetWidth gets the width of the terminal, which is used to determine how many columns can be dropped when the file name is abbreviated.

Get_dir_detail gets all the file names under the specified directory.

Getpermission Gets the file permission information according to the file permission bit St_mode, which is represented by a string.

Print_file_info output file Information according to the file pointer.

Search_file_info all files under the processing directory.

Init is processed separately depending on whether the path is a file or a directory.

Print_simple only output file name, that is, abbreviated display


Code:

#include <stdio.h> #include <dirent.h> #include <stdlib.h> #include <libgen.h> #include <sys /stat.h> #include <string.h> #include <time.h> #include <pwd.h> #include <grp.h> #include <sys/ioctl.h> #include <unistd.h> #define Max_file 1000/* Save file name and file directory */typedef struct item{char d_name[256    ]; Char dir_name[256];}    File_item;file_item files[max_file];/* Save file information */typedef struct item_info{unsigned int i_node;    Char permission[16];    Short owner;    Short Group;    off_t size;    time_t Mod_time;    nlink_t Link_num; Char name[256];} Info;int is_detail;int size_of_path;int terminalwidth;/* Get user name */const char *uid_to_name (short uid) {structpasswd *pw_pt R;if ((pw_ptr = Getpwuid (uid)) = = NULL) return "Unknown"; Elsereturn pw_ptr->pw_name;} /* Get group name */const Char *gid_to_name (short gid) {struct Group *grp_ptr;if ((grp_ptr = Getgrgid (gid)) = = NULL) return "Unk Nown "; Elsereturn grp_ptr->gr_name;} /* Compare function */int cmp (const void *a, const void *b) {return strcasecmp ((* (* (File_item *) a). D_name, (* (File_item *) b). D_name);}    /* Get terminal width */void getwidth () {struct winsize wbuf;    Terminalwidth = 80;             if (Isatty (Stdout_fileno)) {if (IOCTL (Stdout_fileno, Tiocgwinsz, &wbuf) = =-1 | | wbuf.ws_col = = 0) {            Char *TP;        if (tp = getenv ("COLUMNS")) Terminalwidth = atoi (TP);    } else Terminalwidth = Wbuf.ws_col; } return;    }/* get all filenames */void get_dir_detail (const char* dirname) {dir* dir;    struct dirent* DRT;    int cur = 0;    /* Open Directory */dir = Opendir (dirname);        if (dir = = NULL) {perror ("Read Directroy Error.");    Return        }/* Traverse directory */while ((DRT = Readdir (dir)) = NULL) {file_item* Cur_node = files + cur; /* Ignore. And.. Directory */if ((strcmp (Drt->d_name, ".") ==0) | | (strcmp (Drt->d_name, "..")        ==0)) continue;            if (drt->d_name[0] = = '. ')        Continue Size_Of_path + +;        cur++;            if (cur >= max_file) {printf ("Too many files!\n");        Exit (-1);        }/* File name */strcpy (cur_node->d_name,drt->d_name);        /* Directory name */strcpy (cur_node->dir_name,dirname);    strcat (Cur_node->dir_name,drt->d_name); } closedir (dir);}    /* Get file Permissions */void getpermission (mode_t st_mode, char* permission) {/* Initialize 111000000 */unsigned int mask = 0700;    static const char* perm[] = {"---", "--x", "-w-", "-wx", "r--", "R-x", "rw-", "rwx"};    char type;    if (S_isreg (st_mode)) type = '-';    else if (S_isdir (st_mode)) type = ' d ';    else if (S_ISCHR (st_mode)) type = ' C ';    else if (S_islnk (st_mode)) type = ' L ';    else type = '? ';    Permission[0] = type;    /* Calculate permissions */int i = 3;    char* ptr = permission + 1;        while (i>0) {*ptr++ = perm[(St_mode & Mask) >> (i-1) *3][0];        *ptr++ = perm[(St_mode & Mask) >> (i-1) *3][1]; *ptr++ = perm[(St_mode & Mask) >> (i-1) *3][2];        i--;    mask>>=3;    }}/* output File Information */void Print_file_info (info *file_info) {/* format conversion */unsigned fsize = file_info->size;    Char ftime[64];    strcpy (Ftime,ctime (&file_info->mod_time));    Ftime[strlen (Ftime)-1] = ' + ';    int i = 8;    printf ("%10s", file_info->permission);    printf ("%3i", file_info->link_num);    printf ("%14s", Uid_to_name (File_info->owner));    printf ("%14s", Gid_to_name (File_info->group));    printf ("%8u", fsize);    printf ("%26s", ftime); printf ("%s \ n", file_info->name);}    /* Traversal handles All Files */void search_file_info () {struct stat file_stat;    int cur = 0;    Info File_info;        /* Traverse file */while (cur < size_of_path) {file_item* Cur_node = files + cur;        memset (file_info.permission, ' n ', sizeof (file_info.permission)); if (stat (cur_node->dir_name,&file_stat) = =-1) {perror ("Can ' t get the information of the file.\n"          );  Continue        }/* Get file Permissions */getpermission (file_stat.st_mode,file_info.permission);        /* User ID and group id*/file_info.owner = File_stat.st_uid;        File_info.group = File_stat.st_gid;        /* Modify Time */file_info.mod_time = File_stat.st_atime;        /* File Size */file_info.size = file_stat.st_size;        /* I-node number */File_info.i_node = File_stat.st_ino;        /* Number of links */file_info.link_num = File_stat.st_nlink;        /* Copy file name */strcpy (file_info.name,cur_node->d_name);        /* Print file information */Print_file_info (&file_info);    cur++;    }}/* processing */void init (char* pathname) {size_of_path = 0 depending on whether the initial path is file or directory differentiated;    struct stat file_stat;        if (stat (pathname,&file_stat) = =-1) {perror ("Can ' t get the information of the given path.\n");    Return        }/* Normal file */if (S_isreg (File_stat.st_mode)) {Size_of_path = 1;        char* base_name = basename (pathname);  strcpy (Files[0].d_name, base_name);      strcpy (Files[0].dir_name,pathname);    Return        }/* Directory file */if (S_isdir (File_stat.st_mode)) {/* Unified directory Format */if (Pathname[strlen (pathname)-1]! = '/')            {char* ptr = pathname + strlen (pathname);            *ptr++ = '/';        *ptr = 0;        } get_dir_detail (pathname);    Return    }}void print_simple () {int max_len = 0;    int num_in_row = 0;    int num_in_col = 0;    GetWidth ();    /* Gets the maximum filename length */int i = 1;    Max_len = strlen (files[0].d_name);        while (I < size_of_path) {int cur_len = strlen (files[i].d_name);        Max_len = max_len > Cur_len?max_len:cur_len;    i++;    } Max_len + = 2;    /* count each row and number of columns */num_in_row = Terminalwidth/max_len;    if (size_of_path% Num_in_row = = 0) Num_in_col = size_of_path/num_in_row;    else Num_in_col = Size_of_path/num_in_row + 1;    i = 0;        while (I < num_in_col) {int J;     for (j = 0;j < Num_in_row;++j) {       file_item* cur = files + i + J*num_in_col;        printf ("%-*s", max_len,cur->d_name);        } printf ("\ n");    i++;    }}int Main (int argc,char* argv[]) {is_detail = 0;    /* Set Initial path */char initpath[256]; if (argc = = 1 | |    (argc = = 2 && strcmp (argv[1], "-l") = = 0))        {strcpy (Initpath, "./");        /* Get all Files under directory */init (Initpath);        Qsort (Files,size_of_path,sizeof (files[0]), CMP);        /* Print each file information */if (argc = = 1) print_simple ();        else Search_file_info ();    Exit (0);    } int i = 1;        if (argc > 2 && strcmp (argv[1], "-l") = = 0) {i++;    Is_detail = 1;    } int flag = 1;        while (I < ARGC) {if (!flag) printf ("\ n");        Flag = 0;        strcpy (Initpath,argv[i]);        /* Get all Files under directory */init (Initpath);            if (Size_of_path = = 0) {perror ("Usage error\n");        Exit (-1); } qsort (Files,size_of_path,sizeof (fiLes[0]), CMP);        if (is_detail) {/* Print each file information */Search_file_info ();        } else {/* Print a brief message */Print_simple ();    } i++; } return 0;}


Post a Photo:


Implementation of LS command

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.