Simple implementation of the LS command under Linux

Source: Internet
Author: User
Tags sprintf strcmp

At the end of the semester, the Linux practice class teacher is very kind, decorate is a big job to get started: Implement a simple version of the LS command. Three files, upload first.

Ls2.c

#include <stdio.h> #include "ls_header.h" int main (int argc, char **argv) {///processing parameter, Lslong with the-l parameter, Lsshort for L with no-l parameter s command int i;if (argc = = 1) {/* ls. */lsshort ("./"); return 0;} if (argc = = 2 &&!strcmp (argv[1], "-l")) {/* ls-l. */lslong ("./"); return 0;} if (argc > 2 &&!strcmp (argv[1], "-l")) {/* ls-l dirname */for (i = 2; i < argc; + + i) {printf ("%s:\n", arg V[i]); Lslong (Argv[i]); if (i! = argc-1) printf ("\ n");} return 0;} else {/* ls dirname */for (i = 1; i < argc; + + i) {printf ("%s:\n", Argv[i]); Lsshort (Argv[i]); if (i! = argc-1) printf ("\ n ");} return 0;} return 0;}

Ls_header.h

#include <stdio.h> #include <dirent.h>//for DIR, dirent#include <string.h> #include <sys/ioctl.h > #include <unistd.h> #include "ls_util.h"//structstruct attribute file_attribute[200]; Maximum 200void Lslong (char *dirname) {DIR *mydir = Opendir (dirname);/* Directory */char Filename[20];int file_num = 0 if (Mydir = = NULL) {//displays details of a single file strcpy (filename, dirname); Ls_long_file ("./", filename, &file_attribute[0]); + + File_num;} else {//Consider a case where the user input folder does not have a backslash entered int len = strlen (dirname), if (dirname[len-1]! = '/') {Dirname[len] = '/';d irname[len+1] = ' ';} Loop to get all the file names under the current directory and store them in a custom struct struct dirent *mydirent;/* file */while ((mydirent = Readdir (mydir))! = NULL) {char file name[20];strcpy (filename, mydirent->d_name);//cannot be a hidden file if (!strcmp (filename, ".") | |!strcmp (filename, ".") | | FILENAME[0]! = '. ') {ls_long_file (dirname, filename, &file_attribute[file_num + +]);}} Closedir (Mydir);} Sort by file name struct attribute Temp;char Filename1[20];char filename2[20];int I, j;for (i = 0; i < File_num; ++i) {for (j = i + 1; j < File_num; + + j) {strcpy (filename1, File_attribute[i].file name); strcpy (filename2, file_attribute[j].filename); if (strcmp (filename1, filename2) > 0) {temp = File_attribute[i] ; File_attribute[i] = file_attribute[j];file_attribute[j] = temp;}}} When formatting the output, consider the range of each property value int max_mode = 0;int Max_links = 0;int Max_user_name = 0;int Max_group_name = 0;int max_size = 0;int m Ax_mtime = 0;int Max_filename = 0;int Max_extra = 0;for (i = 0; i < file_num; + + i) {if (Max_mode < strlen (file_attr Ibute[i].mode)) {Max_mode = strlen (File_attribute[i].mode);} if (Max_links < F (file_attribute[i].links)) {max_links = f (file_attribute[i].links);} if (Max_user_name < strlen (file_attribute[i].user_name)) {max_user_name = strlen (file_attribute[i].user_name);} if (Max_group_name < strlen (file_attribute[i].group_name)) {max_group_name = strlen (file_attribute[i].group_name) ;} if (Max_size < F (file_attribute[i].size)) {max_size = f (file_attribute[i].size);} if (Max_mtime < strlen (file_attribute[i].mtime)) {max_mtime = strlen (file_attribute[i].mtime);} if (Max_filename < strlen (file_attribute[i].filename)) {max_filename = strlen (file_attribute[i].filename);} if (Max_extra < strlen (File_attribute[i].extra)) {Max_extra = strlen (File_attribute[i].extra);}} for (i = 0; i < File_num; ++i) {char format[50];//defines the format of the output sprintf (format, "%%%ds%%%dd%%%ds%%%ds%%%dld%%%ds%%s%%s\n ", Max_mode, Max_links, Max_user_name, Max_group_name, max_size,max_mtime);//output printf in the defined output format (format, File_ Attribute[i].mode, File_attribute[i].links, File_attribute[i].user_name, File_attribute[i].group_name, File_ Attribute[i].size, File_attribute[i].mtime, File_attribute[i].filename, File_attribute[i].extra);}} Handle the LS command without the-l parameter void Lsshort (char *dirname) {DIR *mydir = Opendir (dirname);/* Directory *///is used to temporarily store all filenames in the directory to be displayed, you can see Up to 200 files can be supported, but each file name is up to 20char filenames[200][20];int file_num = 0;if (Mydir = = NULL) {//display the file directly in printf ("%s\ n ", dirname); return;}  else {//loop check how many files are below and put the file name all in the filenames array struct dirent *mydirent;/* file */while ((mydirent = Readdir (mydir)) = NULL) {Char fname[20];strcpy (fname, mydirent->d_name); if (fname[0]! = '. ') {strcpy (Filenames[file_num], mydirent->d_name); File_num + +;}} Closedir (Mydir);} The file names are sorted int i, J;char temp[20];for (i = 0; i < file_num; + + i) {for (j = i+1; J < File_num; + + j) {if (strcmp (filenames [i], filenames[j]) > 0) {strcpy (temp, filenames[i]); strcpy (Filenames[i], filenames[j]); strcpy (filenames[j], temp);}}  Determine the length of the longest file name in all files int max_len = 0;for (i = 0; i < file_num; + + i) {int len = strlen (Filenames[i]); if (Len > Max_len) {max_len = len;}} Get the current endpoint resolution int cols = 80;int lines = 24;getterminatorsize (&cols, &lines); Char format[20];sprintf (format, "%%-% DS ", Max_len);//format output, when the length is greater than the number of columns of the terminal, newline int current_len = 0;for (i = 0; i < File_num; + + i) {printf (format, filenames[i]); Current_len + = Max_len + 2;if (Current_len + Max_len + 2 > cols) {PRintf ("\ n"); current_len = 0;}}  printf ("\ n");}

Ls_util.h

#include <stdio.h> #include <sys/stat.h>//this header file to get the details of the file # include <string.h> #include <time.h >//time header file # include <pwd.h>//used to get the user name # include <grp.h>//used to get the group name//struct, used to store each attribute value to output struct ATTRIBUTE{CHAR mode[10];//file attributes and Permissions int links;//link number char user_name[20];//user name Char group_name[20];//user Group long size;//file size char mtime[20] ;//Last Modified time char filename[255];//file name char extra[3];//used to display the time to add "*" (executable file) or "/" (directory) extra string};//computes an integer n has several int f (long N) {INT ret = 0;while (n) {n = n/10;++ ret;} return ret;}      Gets the number of columns and rows of the terminal void getterminatorsize (int *cols, int *lines) {#ifdef tiocgsize struct ttysize ts;      IOCTL (Stdin_fileno, Tiocgsize, &ts);      *cols = Ts.ts_cols;  *lines = Ts.ts_lines;      #elif defined (tiocgwinsz) struct winsize ts;      IOCTL (Stdin_fileno, Tiocgwinsz, &ts);      *cols = Ts.ws_col;  *lines = Ts.ws_row;     #endif/* tiocgsize */}//by mode int, get the actual string to be displayed void Mode2str (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 (S_islnk (mode)) str[0] = ' l ';    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 ';} Based on the user's ID value, the user name void Uid2str (uid_t uid, char *user_name)/* will be converted to username */{struct passwd *pw_ptr;pw_ptr = Getpwuid ( UID), if (pw_ptr = = NULL) {sprintf (user_name, "%d", UID),} else {strcpy (user_name, pw_ptr->pw_name);}} Based on the ID value of the user group, the user group name void Gid2str (gid_t gid, char *group_name)/* will be converted to username */{struct Group *grp_ptr;grp_ptr = Getgr GID (GID), if (grp_ptr = = NULL) {sprintf (group_name, "%d", GID),} else {strcpy (group_name, Grp_ptr->gr_name);}} Time formatted string, note here I've removed the previous week and the following year with void TimE2str (time_t t, char *time_str) {strcpy (Time_str, CTime (&t) + 4); time_str[12] = ' n ';} To display the details of a file and place the information in the struct attribute void Ls_long_file (char *dirname, char *filename, struct attribute *file_attri) {//root According to the folder name and filename get full name char fullname[256];strcpy (fullname, dirname); strcpy (fullname + strlen (dirname), filename); struct STAT  MYSTAT;IF (Stat (fullname, &mystat) = =-1) {printf ("Ls_long_file:stat error\n");} else {//here refer to <stat.h> header file int  mode = (int) Mystat.st_mode;int links = (int) mystat.st_nlink;int UID = (int) mystat.st_uid;int gid = (int) Mystat.st_gid;long size = (long) Mystat.st_size;long mtime = (long) Mystat.st_mtime;char str_mode[10];/* file type and permissions, "drwx RWX---"*/char str_user_name[20];char str_group_name[20];char str_mtime[20];//Here is a direct call to the above function, batting practice does not explain the MODE2STR (mode, Str_mode); Uid2str (uid, str_user_name); Gid2str (GID, str_group_name); Time2str (Mtime, str_mtime); char extra[3] = "\0\0" if (str_mode[0] = = ' d ') {extra[0] = '/';} else if (str_mode[0] = = '-' && str_mode[3] = = ' x ') {extra[0] = ' * ';} stored in the structure strcpy (File_attri->mode, str_mode); file_attri->links = links;strcpy (File_attri->user_name, Str_ USER_NAME); strcpy (File_attri->group_name, str_group_name); file_attri->size = size;strcpy (file_attri-> Mtime, Str_mtime); strcpy (file_attri->filename, filename); strcpy (File_attri->extra, extra);// The result is probably the following situation.!/* drwxr-xr-x 5 halfish halfish 4096 December 10:35 downloads/*}}


Simple implementation of the LS command under Linux

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.