C语言实现的linux下ls命令


用C语言实现linux下的ls -l命令。与文件相关的结构体、函数等等知识请看"stat结构体以及文件相关函数"
[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. #include <sys/types.h>  
  4.   
  5. #include <dirent.h>  
  6.   
  7. #include <sys/stat.h>  
  8.   
  9. #include <string.h>  
  10.   
  11. #include <unistd.h>  
  12.   
  13. #include <pwd.h>  
  14.   
  15. #include <grp.h>  
  16.   
  17.    
  18.   
  19. void do_ls(char *dirname);  
  20.   
  21. void dostat(char *filename);  
  22.   
  23. void show_file_info(char *filename, struct stat *info_p);  
  24.   
  25. void mode_to_letters(int mode, char * str);  
  26.   
  27. char *uid_to_name(uid_t uid);  
  28.   
  29. char *gid_to_name(gid_t gid);  
  30.   
  31.    
  32.   
  33. int main(int argc, char **argv)  
  34.   
  35. {  
  36.   
  37.   if (argc == 1)  
  38.   
  39.   {   
  40.   
  41.     do_ls( "." );  
  42.   
  43.   }  
  44.   
  45.   else  
  46.   
  47.   {   
  48.   
  49.     while ( --argc )  
  50.   
  51.     {  
  52.   
  53.       printf("%s:\n", *++argv );  
  54.   
  55.       chdir(*argv); //切换到指定目录后再显示该目录的内容  
  56.   
  57.       do_ls( *argv );  
  58.   
  59.       chdir(""); //再回到当前工作目录来  
  60.   
  61.     }  
  62.   
  63.   }  
  64.   
  65.   return 0;  
  66.   
  67. }  
  68.   
  69.    
  70.   
  71. void do_ls( char * dirname )  
  72.   
  73. {  
  74.   
  75.   DIR    *dir_ptr;  
  76.   
  77.   struct dirent  *direntp;  
  78.   
  79.   /* 
  80.  
  81.   struct dirent 
  82.  
  83.   { 
  84.  
  85.     ino_t d_nio; 
  86.  
  87.     ff_t d_off; 
  88.  
  89.     signed short int d_reclen; 
  90.  
  91.     unsigned char d_type; 
  92.  
  93.     har d_name[256];   
  94.  
  95.   } 
  96.  
  97.   d_ino:目录进入点的inode 
  98.  
  99.   d_off:目录文件开头至此目录进入点的位移 
  100.  
  101.   d_reclen:d_name的长度,不包含NULL字符 
  102.  
  103.   d_type:d_ame所指文件类型 
  104.  
  105.   d_name:文件名 
  106.  
  107.   */  
  108.   
  109.   /* 
  110.  
  111.     opendir函数用来打开参数name指定的目录, 
  112.  
  113.     并返回DIR *形态的目录流 
  114.  
  115.   */  
  116.   
  117.   if ( ( dir_ptr = opendir( dirname ) ) == NULL )   
  118.   
  119.   {  
  120.   
  121.     fprintf(stderr,"ls1: cannot open %s, not a directory. treat as a file shown below:\n", dirname);  
  122.   
  123.     dostat( dirname ); //如果不是目录就当作文件来显示其属性  
  124.   
  125.   }  
  126.   
  127.   else  
  128.   
  129.   {  
  130.   
  131.     /* 
  132.  
  133.       readdir返回参数dir目录流的下个目录进入点 
  134.  
  135.     */  
  136.   
  137.     while ( ( direntp = readdir( dir_ptr ) ) != NULL )  
  138.   
  139.     {   
  140.   
  141.       dostat( direntp->d_name );/*逐个显示目录里文件信息*/  
  142.   
  143.     }  
  144.   
  145.     closedir(dir_ptr);  
  146.   
  147.   }  
  148.   
  149. }  
  150.   
  151.    
  152.   
  153. void dostat( char *filename )  
  154.   
  155. {  
  156.   
  157.   struct stat info;  
  158.   
  159.   if ( stat(filename, &info) == -1 )    /*取文件信息失败*/  
  160.   
  161.   {    
  162.   
  163.     perror( filename );  
  164.   
  165.   }  
  166.   
  167.   else          /*显示文件信息*/  
  168.   
  169.   {   
  170.   
  171.     show_file_info( filename, &info );  
  172.   
  173.   }  
  174.   
  175. }  
  176.   
  177.    
  178.   
  179. void show_file_info(char *filename, struct stat *info_p)  
  180.   
  181. {  
  182.   
  183.   char modestr[11];  
  184.   
  185.    
  186.   
  187.   mode_to_letters(info_p->st_mode, modestr);  
  188.   
  189.    
  190.   
  191.   printf("%s"  , modestr);  
  192.   
  193.   //st_nlink连接该文件的硬链接数,刚建立的文件值为1  
  194.   
  195.   printf("%4d "  , (int) info_p->st_nlink);    
  196.   
  197.   printf("%-8s " , uid_to_name(info_p->st_uid));  
  198.   
  199.   printf("%-8s " , gid_to_name(info_p->st_gid));  
  200.   
  201.   printf("%8ld " , (long)info_p->st_size);  
  202.   
  203.   printf("%.12s ", 4+ctime(&info_p->st_mtime));  
  204.   
  205.   printf("%s\n" , filename);  
  206.   
  207. }  
  208.   
  209.    
  210.   
  211. void mode_to_letters(int mode, char * str)  
  212.   
  213. {  
  214.   
  215.   strcpy(str, "----------");           /* default=无参数 */  
  216.   
  217.    
  218.   
  219.   if (S_ISDIR(mode))    
  220.   
  221.     str[0] = 'd';    /* 目录      */  
  222.   
  223.   if (S_ISCHR(mode))   
  224.   
  225.     str[0] = 'c';    /* 字符设备   */  
  226.   
  227.   if (S_ISBLK(mode))    
  228.   
  229.     str[0] = 'b';    /* 块设备     */  
  230.   
  231.    
  232.   
  233.   if (mode & S_IRUSR)   
  234.   
  235.     str[1] = 'r';    /* 用户权限  */  
  236.   
  237.   if (mode & S_IWUSR)   
  238.   
  239.     str[2] = 'w';  
  240.   
  241.   if (mode & S_IXUSR)   
  242.   
  243.     str[3] = 'x';  
  244.   
  245.    
  246.   
  247.   if (mode & S_IRGRP)   
  248.   
  249.     str[4] = 'r';    /* 组权限 */  
  250.   
  251.   if (mode & S_IWGRP)   
  252.   
  253.     str[5] = 'w';  
  254.   
  255.   if (mode & S_IXGRP)  
  256.   
  257.     str[6] = 'x';  
  258.   
  259.    
  260.   
  261.   if (mode & S_IROTH)   
  262.   
  263.     str[7] = 'r';    /* 其人的权限 */  
  264.   
  265.   if (mode & S_IWOTH)   
  266.   
  267.     str[8] = 'w';  
  268.   
  269.   if (mode & S_IXOTH)   
  270.   
  271.     str[9] = 'x';  
  272.   
  273. }  
  274.   
  275.    
  276.   
  277. char *uid_to_name(uid_t uid)  
  278.   
  279. {  
  280.   
  281.   struct  passwd *pw_ptr;  
  282.   
  283.   static  char numstr[10];  
  284.   
  285.   //获取用户ID  
  286.   
  287.   if ((pw_ptr = getpwuid(uid)) == NULL)  
  288.   
  289.   {  
  290.   
  291.     sprintf(numstr,"%d", uid);  
  292.   
  293.     return numstr;  
  294.   
  295.   }  
  296.   
  297.   else  
  298.   
  299.   {   
  300.   
  301.     return pw_ptr->pw_name ;  
  302.   
  303.   }  
  304.   
  305. }  
  306.   
  307.    
  308.   
  309. char *gid_to_name( gid_t gid )  
  310.   
  311. {  
  312.   
  313.   struct group *grp_ptr;  
  314.   
  315.   static  char numstr[10];  
  316.   
  317.   //获取组ID  
  318.   
  319.   if ((grp_ptr = getgrgid(gid)) == NULL)  
  320.   
  321.   {  
  322.   
  323.     sprintf(numstr,"%d", gid);  
  324.   
  325.     return numstr;  
  326.   
  327.   }  
  328.   
  329.   else  
  330.   
  331.   {   
  332.   
  333.     return grp_ptr->gr_name;  
  334.   
  335.   }  
  336.   
  337. }  
myls命令包含9个选项: (1) myls : 在缺省选项的情况下,列出当前文件夹下的普通文件(不包含隐藏文件)。 例如:当前目录包含文件home1.c, home2.c, .home3.c,输入myls后,列出的文件名为home1.c, home2.c. (2) myls –a: 列出当前文件夹下的所有文件(包含隐藏文件)。 例如:当前目录包含文件home1.c、home2.c、.home3.c,输入myls -a后,列出所有的文件名为home1.c, home2.c, .home3.c. (3) myls –l: 列出当前文件夹下普通文件的详细信息,包括文件模式,文件链接数,文件所属用户,文件所属用户组,文件大小,文件最后修改时间,文件名。并且在最后一行显示该目录下所显示的文件的文件块数。 例如:显示drwxr-xr-x 3 eli eli 4096 Nov 16 23:07 Desktop (4) myls -R 递归列出文件及其子文件。 例如:当前目录为home, 其中包含文件home1, home2, home3. 其中home1是目录文件,包含文件home11, home12, home2不是目录文件,home3是目录文件,包含文件home31, home32。 输入myls –R后,列出的文件名为 ./home: home1 home2 home3 ./home/home1: home11 home12 ./home/home3: home31 home32. (5) myls –u: 列出当前文件夹下用户x的普通文件,若输入myls -u bb,则显示所属bb的普通文件。 例如:文件home1, home2, home3属于aa,文件tmp1, tmp2, tmp3属于bb, 则若输入myls –u aa, 则显示home1,home2,home3,若输入myls -u bb, 则显示tmp1,tmp2,tmp3。 (6) myls –S: 对文件进行排序,需要输入比较参数。 myls –S 的参数包括: time——按最近修改时间排序 name——按文件名的字典序排序 size——按文件的大小从小到大排序 link——按文件链接数从少到多排序 (7) myls -1: 将当前文件夹下的文件按照一行一个的方式显示。 (8) myls –s: 在各个文件开头显示这个文件的文件块大小。 (9) myls /dirname: 显示/dirname下的文件。 编译 gcc main.c -o myls 执行 ./myls 可加若干参数,具体见上描述 程序并不完整,可能会有BUG,希望广大网友指点,交流~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值