Most of the people working on Linux must have used the basic command 'ls'. I use it many times a day. It is a very useful command when it comes to displaying the contents of a directory and their properties. For those few who have still not used 'ls' its high time now, go to its man page, study it and start using it. Anyways, coming back to the article, this article does not describe the usage of 'ls' command but rather here I try to develop my own 'ls' equivalent 'my_ls'. I'll use C language and will try to develop a full fledged 'ls' command. The article will be divided in several small articles which would collectively cover the whole effort. This article becomes the part-I of the series. Properties of 'ls' covered in this part In this article, we will just cover the basic property where in the contents of the directory are displayed when 'my_ls' is executed. For example: Code: $ my_ls article_function_pointer.txt Desktop Downloads Music Pictures Public testdisk.log test.py Videos worm chmodOctal.txt Documents google output.log practice Templates testfile Unsaved Document 1 vlc The code The following code is the first draft of the implementation : Code: #include<stdio.h> #include<stdlib.h> #include <sys/types.h> #include <dirent.h> int main(void) { char *curr_dir = NULL; DIR *dp = NULL; struct dirent *dptr = NULL; unsigned int count = 0; // Get the value of environment variable PWD curr_dir = getenv("PWD"); if(NULL == curr_dir) { printf("\n ERROR : Could not get the working directory\n"); return -1; } // Open the current directory dp = opendir((const char*)curr_dir); if(NULL == dp) { printf("\n ERROR : Could not open the working directory\n"); return -1; } printf("\n"); // Go through and display all the names (files or folders) // Contained in the directory. for(count = 0; NULL != (dptr = readdir(dp)); count++) { printf("%s ",dptr->d_name); } printf("\n %u", count); return 0; } In the above code, we first fetch the current working directory through the environment variable PWD Since now we get the working directory, we open it and iterate over its contents by reading the directory. With each file/folder encountered, we display the name of it. The Output and the Loopholes The out put of the above code is something like : Code: $ ./my_ls .config .gnome2_private .cache .gstreamer-0.10 worm Unsaved Document 1 testfile testdisk.log article_function_pointer.txt .compiz .macromedia .xsession-errors.old .icons .pulse-cookie Desktop .gtk-bookmarks .bash_logout vlc .lesshst .linuxmint test.py .thumbnails .gnome2 .sudo_as_admin_successful chmodOctal.txt output.log .dmrc .mozilla-thunderbird .ICEauthority .xchm .recently-used.xbel Pictures .gksu.lock Templates .ssh google .mplayer .kde .xchat2 .gvfs .xsession-errors .viminfo .themes .teamviewer .profile .openoffice.org my_ls .. Public Documents .kchmviewer .adobe Music .vim .esd_auth .fontconfig .java Downloads .nautilus .bash_history . .mozilla .gimp-2.6 .gegl-0.0 .gconf .thunderbird .gconfd .Skype .pulse .local Videos practice .dbus While the output of the standard ls command is : Code: $ ls article_function_pointer.txt Desktop Downloads Music output.log practice Templates testfile Unsaved Document 1 vlc chmodOctal.txt Documents google my_ls Pictures Public testdisk.log test.py Videos worm We see that there is a clear difference between the two outputs. The difference visible are : Our utility 'my_ls' shows many files which begin with '.' while ls does not. The output from 'my_ls' is not formatted correctly (For example, executables should be in green, Directories should be in blue etc). The output from 'my_ls' is not in alphabetical order and the display is not in an order. So we see that there are above mentioned 3 short comings. Lets correct them one by one(The first two will be covered in this part while the last one will be covered in part-II). Omitting the files from output that begin with '.' Here is the piece of code : Code: #include<stdio.h> #include<stdlib.h> #include <sys/types.h> #include <dirent.h> int main(void) { char *curr_dir = NULL; DIR *dp = NULL; struct dirent *dptr = NULL; unsigned int count = 0; curr_dir = getenv("PWD"); if(NULL == curr_dir) { printf("\n ERROR : Could not get the working directory\n"); return -1; } dp = opendir((const char*)curr_dir); if(NULL == dp) { printf("\n ERROR : Could not open the working directory\n"); return -1; } printf("\n"); for(count = 0; NULL != (dptr = readdir(dp)); count++) { // Check if the name of the file/folder begins with '.' // If yes, then do not display it. if(dptr->d_name[0] != '.') printf("%s ",dptr->d_name); } return 0; } In the above code, we first fetch the current working directory through the environment variable PWD. Since now we get the working directory, we open it and iterate over its contents by reading the directory. If the name of the file/folder begins with a '.', then just ignore it as the standard 'ls' also does not display the file beginning with '.' if its executed without any flags. With each file/folder (whose name does not begin with '.') encountered, we display the name of it on stdout. Now lets compare the output : Code: $ ./my_ls worm Unsaved Document 1 testfile testdisk.log article_function_pointer.txt Desktop vlc test.py chmodOctal.txt output.log Pictures Templates google my_ls Public Documents Music Downloads Videos practice $ ls article_function_pointer.txt Desktop Downloads Music output.log practice Templates testfile Unsaved Document 1 vlc chmodOctal.txt Documents google my_ls Pictures Public testdisk.log test.py Videos worm We see that the output of 'my_ls' is closer to 'ls' as now there is no file that begins with '.' Getting the Color formatting correct Here is the code : Code: #include<stdio.h> #include<stdlib.h> #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> // Define the color codes as macros #define RESET_COLOR "\e[m" #define MAKE_GREEN "\e[32m" #define MAKE_BLUE "\e[36m" int main(void) { char *curr_dir = NULL; DIR *dp = NULL; struct dirent *dptr = NULL; unsigned int count = 0; // Find the column width of terminal // We will make use of this in part-II // Of this article. struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); curr_dir = getenv("PWD"); if(NULL == curr_dir) { printf("\n ERROR : Could not get the working directory\n"); return -1; } dp = opendir((const char*)curr_dir); if(NULL == dp) { printf("\n ERROR : Could not open the working directory\n"); return -1; } for(count = 0; NULL != (dptr = readdir(dp)); count++) { if(dptr->d_name[0] != '.') { // Check if the file is executable if(!access(dptr->d_name,X_OK)) { int fd = -1; struct stat st; fd = open(dptr->d_name, O_RDONLY, 0); if(-1 == fd) { printf("\n Opening file/Directory failed\n"); return -1; } fstat(fd, &st); // Check if it actaully was a directory with execute // permissions on it. if(S_ISDIR(st.st_mode)) { // If it was a directory, print it in Blue printf(MAKE_BLUE"%s "RESET_COLOR,dptr->d_name); } else { // If it was a normal executable // Print it in green printf(MAKE_GREEN"%s "RESET_COLOR,dptr->d_name); } close(fd); } else { // No executable flag ON // Print it in black(default) printf("%s ",dptr->d_name); } } } printf("\n"); return 0; } In the above code, we first fetch the current working directory through the environment variable PWD Since now we get the working directory, we open it and iterate over its contents by reading the directory. If the name of the file/folder begins with a '.', then just ignore it as the standard 'ls' also does not display the file beginning with '.' if its executed without any flags. Then for every valid file/folder name we see that whether it has execute permissions on it. If execute permissions are there, then for folders we print the name in blue while for files we print the name in green. For all other regular files whose execute permissions are not set, the name is printed in black All these names are printed on stdout. The output of the following code is : Code: $ ./my_ls worm Unsaved Document 1 testfile testdisk.log article_function_pointer.txt Desktop vlc test.py chmodOctal.txt output.log Pictures Templates google my_ls Public Documents Music Downloads my_ls.c Videos practice If you run the above piece on your machine, you will see that the color formatting is present in the output. Other formatting We will take up the following formatting in Part-II. Displaying the output in alphabetical order. Making the display formatting better. Conclusion To Conclude, In this article we studied how to develop a simple utility that works like the standard 'ls' utility. We divided the development in different parts and in this part we learn to display simply the contents of the directory and got their color formatting correct. Will be covering the rest in the coming parts. Stay tuned for more!!!