my_ls 实现LINUX ls命令的i,s,a,l,t,r,R

   首先引用维基百科对ls的定义:ls命令在类unix操作系统中被用于显示文件夹中的内容。ls即list,英文表示为"list directory contents"。

当我们使用Linux时不可避免的使用ls命令,通过自己的敲码,学长的帮助与网上的翻阅资料,本文通过C语言粗略的实现ls的部分功能。如有不足,欢迎指出。.^_^.

目标实现内容:

  • 实现 ls 的 -a、-l、-R、-t、-r、-i、-s 参数,并允许这些参数任意组合.
  • -R 需要通对 / 的遍历测试
  • 界面美观(输出对齐、与颜色显示等)
  • 无资源与内存泄露

首先,要实现ls的功能,首先要知道我们要实现的功能有哪些.

  • a 显示所有文件及目录 (. 开头的隐藏文件也会列出)
  • -l 除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出
  • -r 将文件以相反次序显示(原定依英文字母次序)
  • -t 将文件依建立时间之先后次序列出
  • -R 若目录下有文件,则以下之文件亦皆依序列出
  • -i 查看文件的inode号(inode存储文件的详细信息)
  • -s 列出文件,并显示文件大小

其次,要对自己的my_ls的整体有清晰的而紧密链接的脉络,不然等自己写好再调试的时候会很痛苦。(像我一样)。

话不多说,让我们来看下具体的思路。

目录

目标实现内容:

  负一:argc和argv.

零,一些必要的函数与头文件。

 一.对传入的参数怎么标记(太妙了,我自己是真没想到)

二. 彩色输出文件名。

三. 在my_ls这个程序中有三个主心骨,怎么说,连接着整个程序的运行的三个函数。

  四.输出对齐(这个太坑了)

五.对与一些参数可以在flag之前就先处理掉。

六. code

 2022.4.28 更正:

   实现代码:



  负一:argc和argv.

  对于从命令行获取参数我们的mani()要变成 int main(int argc ,char**argv);

int main(int argc,char*argv[])

  argc 是 argument count的缩写,表示传入main函数的参数个数;

argv表示传入main函数的参数序列或指针,并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径,所以确切的说需要我们输入的main函数的参数个数应该是argc-1个;argv是指向指针的指针,main函数的第二个参数“char *argv[]“也可以替换为 “char **argv“,两者是等价的。 

  比如说: 

./my_ls -i /home

我们运行my_ls 这个程序,  argc 是3 ,argv[0]=./my_ls ,argv[1]=-i,argv[2]=/home;

零,一些必要的函数与头文件。

    (1)stat和lstat用以获取文件信息。

 头文件:

include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

    ​ 函数原型:int stat(const char *path, struct stat *buf)

    ​ 返回值:成功返回0,失败返回-1;

    ​ 参数:文件路径(名),struct stat 类型的结构体

struct stat 结构体详解:

    struct stat
    {
        dev_t     st_dev;     /* ID of device containing file */文件使用的设备号
        ino_t     st_ino;     /* inode number */    索引节点号
        mode_t    st_mode;    /* protection */  文件对应的模式,文件,目录等
        nlink_t   st_nlink;   /* number of hard links */    文件的硬连接数  
        uid_t     st_uid;     /* user ID of owner */    所有者用户识别号
        gid_t     st_gid;     /* group ID of owner */   组识别号  
        dev_t     st_rdev;    /* device ID (if special file) */ 设备文件的设备号
        off_t     st_size;    /* total size, in bytes */ 以字节为单位的文件容量   
        blksize_t st_blksize; /* blocksize for file system I/O */ 包含该文件的磁盘块的大小   
        blkcnt_t  st_blocks;  /* number of 512B blocks allocated */ 该文件所占的磁盘块  
        time_t    st_atime;   /* time of last access */ 最后一次访问该文件的时间   
        time_t    st_mtime;   /* time of last modification */ /最后一次修改该文件的时间   
        time_t    st_ctime;   /* time of last status change */ 最后一次改变该文件状态的时间   
    };
 stat和lstat的功能基本相同,不过lstat不会对目标文件进行解引用(所以我更推荐lstat,以免发生什么奇怪的反应)。

    2.opendir,closedir,readdir,chdir;

相信大家对前三个打开,关闭,读取目录比较熟悉,我这里介绍一下 chdir(在后面实现递归和引用的参数中有指定路径时特别重要)

   函数名: chdir改变当前工作目录到path.
   头文件: #include <dir.h>
    int chdir(const char *path);

   其余一些我在代码中将会注释。

 一.对传入的参数怎么标记(太妙了,我自己是真没想到)

  对于  ls命令的参数要求能任意组合比如 -i 或者 -is 或者 -i -s 。假如我们按正常思路那我们可能要开一个数组来判断传入了什么参数,以及参数的各种组合。这样就略显麻烦了。实际上我们可以通过二进制 来标记。 通过一个int型的flag,对2的倍数进行 与 | 操作。类似这样:

#define PARAM_a 1
#define PARAM_l 2
#define PARAM_R 4
#define PARAM_t 8
#define PARAM_r 16
#define PARAM_i 32
#define PARAM_s 64

 for(int i=1;i<argc;i++)
    {
        if(argv[i][0]=='-')
         {
             for(int j=1;j<strlen(argv[i]);j++)
              {
                  param[cnt++]=argv[i][j];
              }
            num++;
         } 
    }

     //通过flag标记参数
      for(int k=0;k<cnt;k++)
       {
          if(param[k]=='a')
            flag|=PARAM_a;
             else if(param[k]=='l')
            flag|=PARAM_l;
             else if(param[k]=='i')
            flag|=PARAM_i;
             else if(param[k]=='R')
            flag|=PARAM_R;
             else if(param[k]=='r')
            flag|=PARAM_r;
             else if(param[k]=='t')
            flag|=PARAM_t;
             else if(param[k]=='s')
            flag|=PARAM_s;
          
        }

 注意 ‘-’后面就跟着ls的参数。

 同样的对于后面的命令行参数的组合时,也只要判断flag等于哪些参数之和就行了。

ps: 学长说可以通过getpot()函数直接获取参数,还快捷方便。

二. 彩色输出文件名。

   格式:

printf("\033[字背景颜色;字体颜色m字符串\033[0m" );
字背景颜色: 40–49字颜色: 30–39
40: 黑30: 黑
41: 红31: 红
42: 绿32: 绿
43: 黄33: 黄
44: 蓝34: 蓝
45: 紫35: 紫
46: 深绿36: 深绿
47:白色37:白色

  

三. 在my_ls这个程序中有三个主心骨,怎么说,连接着整个程序的运行的三个函数。

display_dir,display_file,display_single.

 1.display_dir,当判断为目录时使用。

  2.display_file,当判断为文件时使用。

  3.display_single彩色输出文件名。

具体的内容请看代码。

  四.输出对齐(这个太坑了

  首先 你要 设几个全局变量

g_max_len  最长文件名 (在display_dir遍历文件时能得到)

g_leave_len 本行剩下的格数。 初始为 MAXROWLEN=155;

h_max  本行最多能输出几个文件名

拿 display_single举例:

 void display_single(char *name,int filecolor)
{
	char colorname[NAME_MAX + 30];
	int i,len,j = 0;
	len = strlen(name);
    h++;
       if(g_leave_len<=g_maxlen||h==h_max)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       sprintf(colorname,"\033[%dm%s\033[0m",filecolor,name);
       printf(" %-s",colorname);

       for(int i=0;i<len;i++)
       {
           if(name[i]<0)
                j++;   
       }
       len=g_maxlen-len+j/3;   //
        
         g_leave_len-=(g_maxlen+10);
       for(int i=0;i<len+6;i++)
		   printf(" ");

}

这边倒数第二个的循环中,为什么要判断name[i]是否小于0呢? 因为文件名里可能有字母啊》》。

而通过strlen()获取字符串长度时,遇到汉字会返回三个字节,所以后面要j/3.

至于h_max,一行最多能放下几个文件名则通过 h_max=g_leave_len/(g_maxlen+15)获取(学长说是一个公式我也不太了解)。

五.对与一些参数可以在flag之前就先处理掉。

后面就不用再flag |与了,在后面参数组合时也能够减轻工作量。

比如-t 按最后修改时间排序,我写了一个time_qsort但是不知道为什么不能在大一点的工作目录下运行,最后还是普通地用了插入排序。

-a则是混入到各个命令参数之间, 比如 -ia 和-i的区别就是多一个判断语句:

 else if(flag==(PARAM_i+PARAM_a))
            {

				       ls_i(name,filecolor);
            }

else if (flag==PARAM_i)
 {
        if(name[0]!='.')
          ls_i(name,filecolor);
}

五.各个参数的实现中比较难的可能就是-R了,

我一开始写的程序中对于普通的目录能够进行遍历,但是一到大点的目录时就会提示 segament fault 段错误,因为一开始我用的是普通的二维数组,测试用例大点就爆了,通过网上查询提示可以用动态数组或者链表,我下面的实现是通过动态数组实现的。

后面遍历 / 目录时又出错了 ,提示我 Permission denied 没有权限    ,后面发现在进行-R有关命令之前需要进入超级用户root模式,在运行程序之前(以Ubuntu为例)

su root
//输入你的密码

之后没有出现上述两个错误了,可是。。。 后面又提示出现了在碰到 /proc的某个文件时提示(自己写的my_error()错命令的作用,可惜不会gdb,Printf大法麻了)没有这个文件no such file or directory   ,实在找不到办法我就只能当读取到/proc的某个文件报错后跳过这个文件了。。。

六. code

下面是代码:

#include<stdio.h>
#include <linux/limits.h> //包含PATH_MAX =260
#include<string.h>
#include<sys/stat.h> //提供 stat函数
#include<sys/types.h>
#include<stdlib.h>
#include<pwd.h>  //找uid
#include<grp.h>  //找gid
#include<time.h>  //转换时间
#include<unistd.h>
#include<dirent.h>
#include<errno.h>  //错误的代码会传到errno中
#define PARAM_NONE 0   //通过二进制 | 来标记flag
#define PARAM_a 1
#define PARAM_l 2
#define PARAM_R 4
#define PARAM_t 8
#define PARAM_r 16
#define PARAM_i 32
#define PARAM_s 64
#define MAXROWLEN  155 
int h=0,h_max=2;
int g_maxlen;  //这个目录下最长的文件名
int g_leave_len = MAXROWLEN;  //本行剩余长度
void my_error(const char * err_string,int line);
void  display_single(char *name ,int color);
void ls_l(struct stat buf,char *name,int color);
void ls_i(char *name,int color);
void ls_s(char * name,int color);
void ls_R(char *path,int flag);
void display_dir(int flag,char*path);
void display_file(int flag,char *filename);
int cmp(const void *_a,const void *_b);

int main(int argc,char*argv[])
{
   
   char path[PATH_MAX+1];   //写入路径
   int flag;  //判断参数。
   struct stat buf;
   int cnt=0,num=0;
   char param[100];
   flag=PARAM_NONE;
   for(int i=1;i<argc;i++)
    {
        if(argv[i][0]=='-')
         {
             for(int j=1;j<strlen(argv[i]);j++)
              {
                  param[cnt++]=argv[i][j];
              }
            num++;
         } 
    }

     //通过flag标记参数
      for(int k=0;k<cnt;k++)
       {
          if(param[k]=='a')
            flag|=PARAM_a;
             else if(param[k]=='l')
            flag|=PARAM_l;
             else if(param[k]=='i')
            flag|=PARAM_i;
             else if(param[k]=='R')
            flag|=PARAM_R;
             else if(param[k]=='r')
            flag|=PARAM_r;
             else if(param[k]=='t')
            flag|=PARAM_t;
             else if(param[k]=='s')
            flag|=PARAM_s;
          
        }

         if(num+1==argc)  //说明命令中没有路径,所以默认路径为./当前目录下
       {   //printf("1\n");
          strcpy(path,"./");
          path[2]='\0';
           display_dir(flag,path);
          return 0;
       }
       
       for(int m=1;m<argc;m++)
         {    
              if(argv[m][0]=='-')
               {
                   
                   continue;
               }
              
              else
               {  

                   if(lstat(argv[m],&buf)==-1)
                    {
                        my_error("lstat",__LINE__);
                    }

                   if(S_ISDIR(buf.st_mode))  //是不是目录
                    {  strcpy(path,argv[m]);
                      if(path[strlen(argv[m])-1]!='/')
                         {
                           path[strlen(argv[m])]='/';
                           path[strlen(argv[m])+1]='\0';
                         }
                         else
                         {
                             path[strlen(argv[m])]='\0';
                         }

                         printf("%s\n",path);
                         if(chdir(path)==-1)
                          {
                            my_error("chdir",__LINE__);
                          }
                        display_dir(flag,path);
                    }

                   else  //是文件
                    {   
                        strcpy(path,argv[m]);
                        display_file(flag,path);

                    } 
                    printf("\n");
               }
         }
         return 0;
}

void my_error(const char * err_string,int line)   //报错函数
{
    fprintf(stderr,"line:%d ",line);
    perror(err_string);
    exit(1);
}

int cmp(const void *_a,const void *_b)  
{
    char *a=(char*)_a;
    char *b=(char*)_b;
    return strcmp(a,b);
}

 void display_single(char *name,int filecolor)   //打印文件名
{
	char colorname[NAME_MAX + 30];
	int i,len,j = 0;
	len = strlen(name);
    h++;
       if(g_leave_len<=g_maxlen||h==h_max)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       sprintf(colorname,"\033[%dm%s\033[0m",filecolor,name);
       printf(" %-s",colorname);

       for(int i=0;i<len;i++)
       {
           if(name[i]<0)
                j++;   
       }
       len=g_maxlen-len+j/3;
        
         g_leave_len-=(g_maxlen+10);
       for(int i=0;i<len+6;i++)
		   printf(" ");

}

void ls_l(struct stat buf,char *name,int color)
{
       char colorname[PATH_MAX+1];
       struct passwd *uid;
       struct group *gid;
       char mtime[100];
          //文档类别
         if(S_ISLNK(buf.st_mode))
          printf("l");
          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");

          //user 权限
          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("-");
          

          //group 权限
          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("-");

          //other 权限
          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("%4lu ",buf.st_nlink);
          //uid和gid
          uid=getpwuid(buf.st_uid);
          gid=getgrgid(buf.st_uid);
          if(uid==NULL||gid==NULL)
           {
               printf("can't get id");
               return ; // __LINE__正在编译的行号
           }
          printf("%-8s  ",uid->pw_name);
          printf("%-8s",gid->gr_name);
           
           //文档容量大小
          printf("%8ld  ",buf.st_size);
          //最后修改时间
          strcpy(mtime,ctime(&buf.st_mtime));
          mtime[strlen(mtime)-1]='\0';  //不然会换行
          printf("%s",mtime);
          sprintf(colorname,"\033[%dm%s\033[0m",color,name);
          printf(" %-s\n",colorname);



}

void ls_i(char *name,int color)
{    struct stat buf;
    if(lstat(name,&buf)==-1)
    {
        my_error("lstat",__LINE__);
    }
    int j=0,len=strlen(name);
       char colorname[NAME_MAX+1];
       h++;
       g_leave_len-=(g_maxlen+10);
       if(g_leave_len<=g_maxlen||h==h_max)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       printf("%7ld",buf.st_ino);
       sprintf(colorname,"\033[%dm%s\033[0m",color,name);
       printf(" %-s",colorname);

       for(int i=0;i<len;i++)
       {
           if(name[i]<0)
                j++;   
       }
       len=g_maxlen-len+j/3;

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


void ls_s(char * name,int color)
{   struct stat buf;
    if(lstat(name,&buf)==-1)
    {
        my_error("lstat",__LINE__);
    }
    int j=0,len=strlen(name);
       char colorname[NAME_MAX+1];
       g_leave_len-=(g_maxlen+12);
       if(g_leave_len<=g_maxlen)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       printf("%3d",buf.st_blocks/2);
       sprintf(colorname,"\033[%dm%s\033[0m",color,name);
       printf(" %-s",colorname);
       h++;
       if(h==h_max)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       
        else
        {
       for(int i=0;i<len;i++)
       {
           if(name[i]<0)
                j++;   
       }
       len=g_maxlen-len+j/3;
        
       for(int i=0;i<len+1;i++)
		   printf(" ");
        }
}

void ls_R(char*name,int flag)  
 
{
DIR * dir;
struct dirent  *ptr;
int     i,count = 0;
struct stat buf;
char name_dir[10000];
if(chdir(name)<0)                              //将输入的目录改为当前目录,下面操作的前提
{ 
    if(lstat(name,&buf)==-1)
          {  if(errno==13)
              { printf("Permission denied\n");
                return;
              }
              else if(strncmp(name,"/proc",4)==0)
                 { printf("this is a /proc file\n");
                   return;
                 }
            else 
             my_error("lstat",__LINE__);
          }
}
if(getcwd(name_dir,10000)<0){
  my_error("getcwd",__LINE__);                   //获取当前目录的绝对路径(重要,下面的打开目录的操作需要这个路径,否则需要手动添加)
}
 printf("%s:\n",name_dir);
 
 dir = opendir(name_dir);     //用新获得的路径打开目录
if(dir==NULL){
  my_error("opendir",__LINE__);
}

  g_maxlen=0;
while((ptr = readdir(dir))!=NULL){
  if(g_maxlen<strlen(ptr->d_name))
         g_maxlen = strlen(ptr->d_name);
    count++;
}
closedir(dir);
 
//动态数组(用静态数组会爆)
  char**filenames =(char**)malloc(count*sizeof(char*));    //要进行初始化 
  memset(filenames,0,sizeof(char*)*count);
 
for(i=0;i<count;i++){
 
  filenames[i]=(char*)malloc(256*sizeof(char));
  memset(filenames[i],0,sizeof(char)*256);
}
 
 
int j,len=strlen(name_dir);
dir = opendir(name_dir);
for(i=0;i<count;i++){
    ptr = readdir(dir);
    if(ptr == NULL){
      my_error("readdir",__LINE__);
    }
 
    strcat(filenames[i],ptr->d_name);   
}
for(i=0;i<count;i++)
   display_file(flag,filenames[i]);
  printf("\n");
                          //递归实现核心部分
 
      for(i=0;i<count;i++){
 
          if(lstat(filenames[i],&buf)==-1)
          {  if(errno==13)
              { printf("Permission denied\n");
                return;
              }
              else if(strncmp(filenames[i],"/proc",4)==0)
                 { printf("this is a /proc file\n");
                   return;
                 }
            else 
             my_error("lstat",__LINE__);
          }
          if(strcmp(filenames[i],"..")==0)
          continue;
          if(filenames[i][0]=='.')
          continue;
          if(S_ISDIR(buf.st_mode)){
            h=0;
            g_leave_len=MAXROWLEN;
            ls_R(filenames[i],flag);
          }
          else if(!S_ISDIR(buf.st_mode))
           {
             continue;
           }
               chdir("../");          //处理完一个目录后返回上一层
        }
 
    
    for(i=0;i<count;i++)
    {
      free(filenames[i]);
    }
    free(filenames);
    closedir(dir);          
    }

void time_quicksort(long filetime[],char filename[256][PATH_MAX+1],int begin,int end)   //大点的目录没有实现??
{  char tmpname[PATH_MAX+1];
   if(begin>=end)
   return ;
    int i=begin;
    int j=end;
    long t;
    long tmp=filetime[begin];
    while(i!=j)
    {
      while(filetime[j]<=tmp&&j>i)
      j--;
      while(filetime[i]>=tmp&&j>i)
      i++;
      if(j>i)
      { //换时间
        t=filetime[i];
        filetime[i]=filetime[j];
        filetime[j]=t;
        //换文件名
        strcpy(tmpname,filename[i]);
        strcpy(filename[i],filename[j]);
        strcpy(filename[j],tmpname);

      }


    }
    filetime[begin]=filetime[i];
    filetime[i]=tmp;
     strcpy(tmpname,filename[i]);
     strcpy(filename[i],filename[begin]);
     strcpy(filename[begin],tmpname);

    time_quicksort(filetime,filename,0,i-1);
     time_quicksort(filetime,filename,i+1,end);
}


//  
void display_file(int flag,char *filename)
{
          int i,j=0,h=0,filecolor=37;//白色
          char name[PATH_MAX+1];
          char lujin[PATH_MAX+1];
          struct stat buf;
        memset(name,'\0',PATH_MAX+1);
          for(i=0;i<strlen(filename);i++)
           {
               if(filename[i]=='/')
                {
                     j=0;
                     h=i;
                     continue;
                }
                name[j++]=filename[i];
           }
            name[j]='\0'; //别漏掉'\0';
           
          

                   //判断颜色
                 if(lstat(filename,&buf)==-1)
                   {    if(errno==13)
                        return;
                        else
                       my_error("lstat",__LINE__);
                   }

     if(S_ISDIR(buf.st_mode))
     {
        filecolor=34;
	}
     
    else if(S_ISBLK(buf.st_mode)){
        filecolor=36;
	} 
 
    if(filecolor == 37&&
    		( (buf.st_mode & S_IXUSR)||
    		  (buf.st_mode & S_IXGRP)||
    		  (buf.st_mode & S_IXOTH)   )  ){
    	filecolor=33;
    }
    
        
              //解析参数 //不用t,r,R,在之前就已经先判断了 //display_dir()时
           if(flag==PARAM_NONE)
            {   if(name[0]!='.')
                {   
				    display_single(name,filecolor);
                }
            }
            else if(flag==PARAM_r)
             {
                 if(name[0]!='.')
                  {   
                     
                      display_single(name,filecolor);
                  }
             }
            else if(flag==PARAM_l)
             {    
                 if(name[0]!='.')
                  {
                      ls_l(buf,name,filecolor);
                  }
             }
           else if(flag==PARAM_i)
            {  if(name[0]!='.')
                {    
                   
				           ls_i(name,filecolor);
                }
            }
            else if(flag==PARAM_a)
            {
				display_single(name,filecolor);
            }
            else if(flag==PARAM_s)
            {   if(name[0]!='.')
                {
               
				    ls_s(name,filecolor);
                }
            }
            else if(flag==(PARAM_i+PARAM_a))
            {
                
				ls_i(name,filecolor);
            }
            else if(flag==(PARAM_a+PARAM_l))
            {
               
				ls_l(buf,name,filecolor);
            }
            else if(flag==(PARAM_i+PARAM_s))
            {   if(name[0]!='.')
              { 
                h_max=g_leave_len/(g_maxlen+15);
                printf("%7ld ",buf.st_ino);
                ls_s(name,filecolor);
              }
            }
            else if(flag==(PARAM_l+PARAM_s))
            {  
              
                if(name[0]!='.')
                {
                   printf("%3ld ",buf.st_blocks/2);
				ls_l(buf,name,filecolor);
                }
            }
            else if(flag==(PARAM_a+PARAM_s))
             {    
                  ls_s(name,filecolor);
             }
            else if(flag==(PARAM_i+PARAM_l))
            {
               
                if(name[0] != '.')
            {
			      	printf("%7ld ",buf.st_ino);
				     ls_l(buf,name,filecolor);
			      }
				
            }
            else if(flag==(PARAM_i+PARAM_s+PARAM_l))
            {
                
                  if(name[0] != '.')
              {
                h_max=g_leave_len/(g_maxlen+15); 
				        printf("%7ld ",buf.st_ino);
                printf("%ld ",buf.st_blocks/2);
				       ls_l(buf,name,filecolor);
			         }
            }
            else if(flag==(PARAM_i+PARAM_a+PARAM_s))
            {
                h_max= g_leave_len/(g_maxlen+15);
                printf("%7ld ",buf.st_ino);
				ls_s(name,filecolor);
            }
            else if(flag==(PARAM_l+PARAM_s+PARAM_a))
            {
                
                printf("%3ld ",buf.st_blocks/2);
				ls_l(buf,name,filecolor);
            }
            else if(flag==(PARAM_i+PARAM_s+PARAM_l))
            {   if(name[0]!='.')
              {

               
                printf("%7ld ",buf.st_ino);
                 printf("%3ld ",buf.st_blocks);
				ls_l(buf,name,filecolor);
              }
            }
            else if(flag==(PARAM_i+PARAM_a+PARAM_l))
            {
               
                printf("%7ld ",buf.st_ino);
				ls_l(buf,name,filecolor);
            }
            else if(flag==(PARAM_i+PARAM_a+PARAM_l+PARAM_s))
            {
                
                printf("%7ld  ",buf.st_ino);
			printf("%3ld  ",buf.st_blocks/2);
				ls_l(buf,name,filecolor);
            }
            
}

void display_dir(int flag,char*path)
{
    DIR *dir;
    struct dirent * ptr;
    int cnt=0;  //计算文件个数
    char filename[256][PATH_MAX+1];
    long filetime[256];
    char tmpfilename[PATH_MAX+1];
    struct stat buf;
    dir=opendir(path);
    if(dir==NULL)
    {
        my_error("opendir",__LINE__);
    }
    while((ptr=readdir(dir))!=NULL)
     {
         int hanzi=0;
         int nohanzi=0;
         for(int i=0;i<strlen(ptr->d_name);i++)
          {    
              if(ptr->d_name[i]<0)
              hanzi++;
              else
              nohanzi++;
          }
        int len=hanzi*2+nohanzi;
        if(g_maxlen<len)
        g_maxlen=len;

        cnt++;
     }
     closedir(dir);

     if(cnt>256)  //过多文件
      printf("%d :too many files under this dir",__LINE__);
      
      dir=opendir(path);
     for(int i=0;i<cnt;i++)
     {
         if((ptr=readdir(dir))==NULL)
          {
              my_error("readdir",__LINE__);
          }

         strncpy(filename[i],path,strlen(path));
         filename[i][strlen(path)]='\0';
         strcat(filename[i],ptr->d_name);
         filename[i][strlen(path)+strlen(ptr->d_name)]='\0';
       //printf("%d %s\n",i,filename[i]);
         

     }
      closedir(dir);
       if(flag&PARAM_t)
        {    
             flag-=PARAM_t;
             struct stat buf;
             for(int i=0;i<cnt;i++)
              {
                  if(lstat(filename[i],&buf)==-1)
                   {
                       my_error("lstat",__LINE__);
                   }
                   filetime[i]=buf.st_mtime;
              }

                for(int i=0;i<cnt;i++)
                   for(int j=i;j<cnt;j++)
                     if(filetime[j]>filetime[i])
                      {
                          long int t;
                          t=filetime[i];
                          filetime[i]=filetime[j];
                          filetime[j]=t;
                      }
            
        }
        else   //用文件名首字母排序
         {
              qsort(filename,cnt,sizeof(filename[0]),cmp);          
 
         }
           //for(int i=0;i<cnt;i++)
            //printf("%d %s\n",i,filename[i]);
          int total=0;
         //计算总量
          if(flag&PARAM_a)   //包括隐藏文件
           {
               for(int i=0;i<cnt;i++)
                {
                    if(lstat(filename[i],&buf)==-1)
                     {
                         my_error("lstat",__LINE__);
                     }
                    total=total+buf.st_blocks/2; //???
                }
           }
          else
           {
                for(int i=0;i<cnt;i++)
                {   
                    if(lstat(filename[i],&buf)==-1)
                     {   
                         my_error("lstat",__LINE__);
                     }
                     if(filename[i][2]!='.')
                    total=total+buf.st_blocks/2; //???
                }
           }

           if((flag&PARAM_l||flag&PARAM_s))
            {
               printf("总用量 %d\n",total);
            }


            if(flag&PARAM_r)
              {    flag-=PARAM_r;
                  if(flag&PARAM_R)  //??
                    {       flag-=PARAM_R;
                            ls_R(path,flag);
                    }
                    else
                     {    
                         for(int i=cnt-1;i>=0;i--)
                           {  
                           display_file(flag,filename[i]);
                           }
                     }
              }
            else
             {
                     if(flag&PARAM_R)
                      {   flag-=PARAM_R;
                          ls_R(path,flag);
                      }
                      else
                       {   
                           for(int i=0;i<cnt;i++)
                            {   
                            display_file(flag,filename[i]);
                            }
                       }

             }

}

 2022.4.28 更正:

现在已经实现全部功能,

1. 主要是对于 -R 时 ,,要注意判断对没有权限的文件判断并跳过。  通过errno  当它=13时,错误为Perrision denied ,即为没有权限,跳过。

2.并且对于文件名时不要用数组,要的话也用动态数组malloc 或者链表,同时主要合适时机malloc

3.以及更正了按文件名排序。

   实现代码:

  

#include<stdio.h>
#include <linux/limits.h> //包含PATH_MAX =260
#include<string.h>
#include<sys/stat.h> //提供 stat函数
#include<sys/types.h>
#include<stdlib.h>
#include<pwd.h>  //找uid
#include<grp.h>  //找gid
#include<time.h>  //转换时间
#include<unistd.h>
#include<dirent.h>
#include<errno.h>
#define PARAM_NONE 0   //通过二进制 | 来标记flag
#define PARAM_a 1
#define PARAM_l 2
#define PARAM_R 4
#define PARAM_t 8
#define PARAM_r 16
#define PARAM_i 32
#define PARAM_s 64
#define MAXROWLEN  155 
int h=0,h_max=2; //h_max一行最多多少个文件名
int flag1=0;  
int g_maxlen;    //最长文件名长度
int g_leave_len = MAXROWLEN;  //本行剩下多少空间
int flag=1;
void my_error(const char * err_string,int line);    
void  display_single(char *name ,int color);
void ls_l(struct stat buf,char *name,int color);
void ls_i(char *name,int color);
void ls_s(char * name,int color);
int ls_R(char *path,int flag);
void display_dir(int flag,char*path);
void display_file(int flag,char *filename);
int cmp(const void *_a,const void *_b);

int main(int argc,char*argv[])
{
   
   char path[PATH_MAX+1];   //写入路径
   int flag;  //判断参数。
   struct stat buf;
   int cnt=0,num=0;
   char param[100];
   flag=PARAM_NONE;
   for(int i=1;i<argc;i++)
    {
        if(argv[i][0]=='-')
         {
             for(int j=1;j<strlen(argv[i]);j++)
              {
                  param[cnt++]=argv[i][j];
              }
            num++;
         } 
    }

     //通过flag标记参数
      for(int k=0;k<cnt;k++)
       {
          if(param[k]=='a')
            flag|=PARAM_a;
             else if(param[k]=='l')
            flag|=PARAM_l;
             else if(param[k]=='i')
            flag|=PARAM_i;
             else if(param[k]=='R')
            flag|=PARAM_R;
             else if(param[k]=='r')
            flag|=PARAM_r;
             else if(param[k]=='t')
            flag|=PARAM_t;
             else if(param[k]=='s')
            flag|=PARAM_s;
          
        }

         if(num+1==argc)  //说明命令中没有路径,所以默认路径为./当前目录下
       {   //printf("1\n");
          strcpy(path,"./");
          path[2]='\0';
           display_dir(flag,path);
          return 0;
       }
       
       for(int m=1;m<argc;m++)
         {    
              if(argv[m][0]=='-')
               {
                   
                   continue;
               }
              
              else
               {  
                   if(lstat(argv[m],&buf)==-1)
                    {   if(errno==13)
                       {

                        printf("Perssion denied\n");
                        errno=0;
                       }
                        else 
                        my_error("lstat",__LINE__);
                    }

                   if(S_ISDIR(buf.st_mode))  //是不是目录
                    {  strcpy(path,argv[m]);
                      if(path[strlen(argv[m])-1]!='/')
                         {
                           path[strlen(argv[m])]='/';  //目录以/结尾
                           path[strlen(argv[m])+1]='\0';
                         }
                         else
                         {
                             path[strlen(argv[m])]='\0';
                         }

                         printf("%s\n",path);
                         if(chdir(path)==-1)   //更换到dath目录下
                          {
                            my_error("chdir",__LINE__);
                          }
                        display_dir(flag,path);
                    }

                   else  //是文件
                    {   
                        strcpy(path,argv[m]);
                        display_file(flag,path);

                    } 
                    printf("\n");
               }
         }
         return 0;
}

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

int cmp(const void *_a,const void *_b)
{
    char *a=(char*)_a;
    char *b=(char*)_b;
    return strcmp(a,b)>0;
}

 void display_single(char *name,int filecolor)
{
	char colorname[NAME_MAX + 30];
	int i,len,j = 0;
	len = strlen(name);
    h++;
       if(g_leave_len<=g_maxlen||h==h_max)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       sprintf(colorname,"\033[%dm%s\033[0m",filecolor,name);
       printf(" %-s",colorname);

       for(int i=0;i<len;i++)
       {
           if(name[i]<0)
                j++;   
       }
       len=g_maxlen-len+j/3;
        
         g_leave_len-=(g_maxlen+10);
       for(int i=0;i<len+6;i++)
		   printf(" ");

}

void ls_l(struct stat buf,char *name,int color)
{
       char colorname[PATH_MAX+1];
       struct passwd *uid;
       struct group *gid;
       char mtime[100];
          //文档类别
         if(S_ISLNK(buf.st_mode))
          printf("l");
          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");

          //user 权限
          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("-");
          

          //group 权限
          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("-");

          //other 权限
          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("%4lu ",buf.st_nlink);
          //uid和gid
          uid=getpwuid(buf.st_uid);
          gid=getgrgid(buf.st_uid);
          if(uid==NULL||gid==NULL)
           {
               printf("can't get id");
               return ; // __LINE__正在编译的行号
           }
          printf("%-8s  ",uid->pw_name);
          printf("%-8s",gid->gr_name);
           
           //文档容量大小
          printf("%8ld  ",buf.st_size);
          //最后修改时间
          strcpy(mtime,ctime(&buf.st_mtime));
          mtime[strlen(mtime)-1]='\0';  //不然会换行
          printf("%s",mtime);
          sprintf(colorname,"\033[%dm%s\033[0m",color,name);
          printf(" %-s\n",colorname);



}

void ls_i(char *name,int color)
{    struct stat buf;
    if(lstat(name,&buf)==-1)
    {
        my_error("lstat",__LINE__);
    }
    int j=0,len=strlen(name);
       char colorname[NAME_MAX+1];
       h++;
       g_leave_len-=(g_maxlen+10);
       if(g_leave_len<=g_maxlen||h==h_max)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       printf("%7ld",buf.st_ino);
       sprintf(colorname,"\033[%dm%s\033[0m",color,name);
       printf(" %-s",colorname);

       for(int i=0;i<len;i++)
       {
           if(name[i]<0)
                j++;   
       }
       len=g_maxlen-len+j/3;

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


void ls_s(char * name,int color)
{   struct stat buf;
    if(lstat(name,&buf)==-1)
    {
        my_error("lstat",__LINE__);
    }
    int j=0,len=strlen(name);
       char colorname[NAME_MAX+1];
       g_leave_len-=(g_maxlen+12);
       if(g_leave_len<=g_maxlen)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       printf("%3d",buf.st_blocks/2);
       sprintf(colorname,"\033[%dm%s\033[0m",color,name);
       printf(" %-s",colorname);
       h++;
       if(h==h_max)
       {
           printf("\n");
          g_leave_len=MAXROWLEN;
          h=0;
       }
       
        else
        {
       for(int i=0;i<len;i++)
       {
           if(name[i]<0)
                j++;   
       }
       len=g_maxlen-len+j/3;
        
       for(int i=0;i<len+1;i++)
		   printf(" ");
        }
}

int ls_R(char*name,int flag)
 
{   
DIR * dir;
struct dirent  *ptr;
int   i,count = 0;
struct stat buf;
char name_dir[1000];
if(chdir(name)<0)                              //将输入的目录改为当前目录,下面操作的前提
{ 
  if(errno==13)
  {  errno=0;
   printf("%s/%s :",name_dir,name);
    printf("no perssion\n"); 
   
  }
  
  else 
  my_error("chdir",__LINE__);
   

    return -1;
   
}
if(getcwd(name_dir,1000)<0){
  
  my_error("getcwd",__LINE__);  
  return 0;                //获取当前目录的绝对路径(重要,下面的打开目录的操作需要这个路径,否则需要手动添加)
}
 printf("%s:\n",name_dir);
 
 dir = opendir(name_dir);     //用新获得的路径打开目录
if(dir==NULL){
  if(errno==13)
  {  errno=0;
    printf("Permission denied 1\n");
    
  }
  
  else 
  {
    my_error("opendir",__LINE__);
    
  }
     
    return 0;
}
while((ptr = readdir(dir))!=NULL){
  if(g_maxlen<strlen(ptr->d_name))
         g_maxlen = strlen(ptr->d_name);
    count++;
}

closedir(dir);
 
//动态数组
  char**filenames =(char**)malloc((count)*sizeof(char*));    //要进行初始化 
  memset(filenames,0,sizeof(char*)*(count));
 
for(i=0;i<count;i++){
 
  filenames[i]=(char*)malloc(1024*sizeof(char));
  memset(filenames[i],0,sizeof(char)*1024);
}
 
 
int j,len=strlen(name_dir),h=0;

dir = opendir(name_dir);
for(i=0;i<count;i++){
    ptr = readdir(dir);
    if(ptr == NULL){
        if(errno==13)
  {     errno=0;
    printf("perssioned error\n");
   
  }   
      else 
      my_error("readdir",__LINE__);

      continue;
    }
   
    strcat(filenames[h++],ptr->d_name);    //这里要注意用之前的初始化
}
for(i=0;i<h;i++)
   {
    
   display_file(flag,filenames[i]);
   }
  printf("\n");

     
      for(i=0;i<h;i++){
            
          if(lstat(filenames[i],&buf)==-1)
          {   //printf("%s/%s\n",name_dir,filenames[i]);
              if(errno==13)
              { printf("%s/%s\n",name_dir,filenames[i]);
                errno=0;
                printf("perrsion denied\n");
                
              }
               free(filenames[i]);
               //my_error("lstat",__LINE__);
                 
             continue;
             
          }
          else
          {
            
          if(strcmp(filenames[i],"..")==0)
          { 
           free(filenames[i]);
          continue;
          }
        else if(strcmp(filenames[i],".")==0)
          { free(filenames[i]);
          continue;
          }
           else if(S_ISDIR(buf.st_mode)){
            if(ls_R(filenames[i],flag)!=-1)
            chdir("../");
            free(filenames[i]);
             
          }
          else if(!S_ISDIR(buf.st_mode))
           {
             continue;
             free(filenames[i]);
           }
           

           }
      }
         
               
                  //处理完一个目录后返回上一层
        
        
    free(filenames);
    closedir(dir);
     return 1;          //在函数开始时打开,结束时关闭
    }


void time_quicksort(long filetime[],char filename[256][PATH_MAX+1],int begin,int end)
{  char tmpname[PATH_MAX+1];
   if(begin>=end)
   return ;
    int i=begin;
    int j=end;
    long t;
    long tmp=filetime[begin];
    while(i!=j)
    {
      while(filetime[j]<=tmp&&j>i)
      j--;
      while(filetime[i]>=tmp&&j>i)
      i++;
      if(j>i)
      { //换时间
        t=filetime[i];
        filetime[i]=filetime[j];
        filetime[j]=t;
        //换文件名
        strcpy(tmpname,filename[i]);
        strcpy(filename[i],filename[j]);
        strcpy(filename[j],tmpname);

      }


    }
    filetime[begin]=filetime[i];
    filetime[i]=tmp;
     strcpy(tmpname,filename[i]);
     strcpy(filename[i],filename[begin]);
     strcpy(filename[begin],tmpname);

    time_quicksort(filetime,filename,0,i-1);
     time_quicksort(filetime,filename,i+1,end);
}


//  
void display_file(int flag,char *filename)
{
          int i,j=0,h=0,filecolor=37;//白色
          char name[PATH_MAX+1];
          char lujin[PATH_MAX+1];
          struct stat buf;
        memset(name,'\0',PATH_MAX+1);
          for(i=0;i<strlen(filename);i++)
           {
               if(filename[i]=='/')
                {
                     j=0;
                     h=i;
                     continue;
                }
                name[j++]=filename[i];
           }
            name[j]='\0'; //别漏掉'\0';
           
          

                   //判断颜色
                 if(lstat(filename,&buf)==-1)
                   {    
                       my_error("lstat",__LINE__);
                   }

     if(S_ISDIR(buf.st_mode))
     {
        filecolor=34;
	}
     
    else if(S_ISBLK(buf.st_mode)){
        filecolor=36;
	} 
 
    if(filecolor == 37&&
    		( (buf.st_mode & S_IXUSR)||
    		  (buf.st_mode & S_IXGRP)||
    		  (buf.st_mode & S_IXOTH)   )  ){
    	filecolor=33;
    }
    
        
              //解析参数 //不用t,r,R,在之前就已经先判断了 //display_dir()时
           if(flag==PARAM_NONE)
            {   if(name[0]!='.')
                {   
				    display_single(name,filecolor);
                }
            }
            else if(flag==PARAM_r)
             {
                 if(name[0]!='.')
                  {   
                     
                      display_single(name,filecolor);
                  }
             }
            else if(flag==PARAM_l)
             {    
                 if(name[0]!='.')
                  {
                      ls_l(buf,name,filecolor);
                  }
             }
           else if(flag==PARAM_i)
            {  if(name[0]!='.')
                {    
                   
				           ls_i(name,filecolor);
                }
            }
            else if(flag==PARAM_a)
            {
				display_single(name,filecolor);
            }
            else if(flag==PARAM_s)
            {   if(name[0]!='.')
                {
               
				    ls_s(name,filecolor);
                }
            }
            else if(flag==(PARAM_i+PARAM_a))
            {
                
				ls_i(name,filecolor);
            }
            else if(flag==(PARAM_a+PARAM_l))
            {
               
				  ls_l(buf,name,filecolor);
            }
            else if(flag==(PARAM_i+PARAM_s))
            {   if(name[0]!='.')
              { 
                h_max=g_leave_len/(g_maxlen+15);   //貌似是一个公式
                printf("%7ld ",buf.st_ino);
                ls_s(name,filecolor);
              }
            }
            else if(flag==(PARAM_l+PARAM_s))
            {  
              
                if(name[0]!='.')
                {
                   printf("%3ld ",buf.st_blocks/2);
				ls_l(buf,name,filecolor);
                }
            }
            else if(flag==(PARAM_a+PARAM_s))
             {    
                  ls_s(name,filecolor);
             }
            else if(flag==(PARAM_i+PARAM_l))
            {
               
                if(name[0] != '.')
            {
			      	printf("%7ld ",buf.st_ino);
				     ls_l(buf,name,filecolor);
			      }
				
            }
            else if(flag==(PARAM_i+PARAM_s+PARAM_l))
            {
                
                  if(name[0] != '.')
              {
                h_max=g_leave_len/(g_maxlen+15); 
				        printf("%7ld ",buf.st_ino);
                printf("%ld ",buf.st_blocks/2);
				       ls_l(buf,name,filecolor);
			         }
            }
            else if(flag==(PARAM_i+PARAM_a+PARAM_s))
            {
                h_max= g_leave_len/(g_maxlen+15);
                printf("%7ld ",buf.st_ino);
				ls_s(name,filecolor);
            }
            else if(flag==(PARAM_l+PARAM_s+PARAM_a))
            {
                
                printf("%3ld ",buf.st_blocks/2);
				ls_l(buf,name,filecolor);
            }
            else if(flag==(PARAM_i+PARAM_s+PARAM_l))
            {   if(name[0]!='.')
              {

               
                printf("%7ld ",buf.st_ino);
                 printf("%3ld ",buf.st_blocks);
				ls_l(buf,name,filecolor);
              }
            }
            else if(flag==(PARAM_i+PARAM_a+PARAM_l))
            {
               
                printf("%7ld ",buf.st_ino);
				ls_l(buf,name,filecolor);
            }
            else if(flag==(PARAM_i+PARAM_a+PARAM_l+PARAM_s))
            {
                
                printf("%7ld  ",buf.st_ino);
			printf("%3ld  ",buf.st_blocks/2);
				ls_l(buf,name,filecolor);
            }
            
}

void display_dir(int flag,char*path)
{
    DIR *dir;
    struct dirent * ptr;
    int cnt=0;  //计算文件个数
    long filetime[256];
    char tmpfilename[PATH_MAX+1];
    struct stat buf;
    dir=opendir(path);
    if(dir==NULL)
    {  
        my_error("opendir",__LINE__);
        return;
    }
    while((ptr=readdir(dir))!=NULL)
     {
         int hanzi=0;
         int nohanzi=0;
         for(int i=0;i<strlen(ptr->d_name);i++)
          {    
              if(ptr->d_name[i]<0)
              hanzi++;
              else
              nohanzi++;
          }
        int len=hanzi*2+nohanzi;
        if(g_maxlen<len)
        g_maxlen=len;

        cnt++;
     }
     closedir(dir);
     
     char **filename=(char**)malloc(sizeof(char *)*(cnt+1));
     for(int i=0;i<cnt+1;i++)
      filename[i]=(char*)malloc(sizeof(char)*100);
      dir=opendir(path);
     for(int i=0;i<cnt;i++)
     {
         if((ptr=readdir(dir))==NULL)
          {
              my_error("readdir",__LINE__);
          }

         strncpy(filename[i],path,strlen(path));
         filename[i][strlen(path)]='\0';
         strcat(filename[i],ptr->d_name);
         filename[i][strlen(path)+strlen(ptr->d_name)]='\0';
       //printf("%d %s\n",i,filename[i]);
         

     }
      closedir(dir);
       if(flag&PARAM_t)
        {    
             flag-=PARAM_t;
             struct stat buf;
             for(int i=0;i<cnt;i++)
              {
                  if(lstat(filename[i],&buf)==-1)
                   {
                       my_error("lstat",__LINE__);
                   }
                   filetime[i]=buf.st_mtime;
              }

              for(int i=0;i<cnt;i++)
                   for(int j=i;j<cnt;j++)
                     if(filetime[j]>filetime[i])
                      {
                          long int t;
                          t=filetime[i];
                          filetime[i]=filetime[j];
                          filetime[j]=t;
                     }
                     //time_quicksort(filetime,filename,0,cnt-1);
            
        }
        else   //用文件名首字母排序
         {
              for(int i=0;i<cnt;i++)
               {
                 for(int j=i+1;j<cnt;j++)
                  {
                    if(strcmp(filename[i],filename[j])>0)
                     {
                       char tmp[1024];
                        strcpy(tmp,filename[i]);
                        strcpy(filename[i],filename[j]);
                        strcpy(filename[j],tmp);
                     }
                  }
               }          
 
         }
           //for(int i=0;i<cnt;i++)
            //printf("%d %s\n",i,filename[i]);
          int total=0;
         //计算总量??
          if(flag&PARAM_a)   //包括隐藏文件
           {
               for(int i=0;i<cnt;i++)
                {
                    if(lstat(filename[i],&buf)==-1)
                     {
                         my_error("lstat",__LINE__);
                     }
                    total=total+buf.st_blocks/2; //???
                }
           }
          else
           {
                for(int i=0;i<cnt;i++)
                {   
                    if(lstat(filename[i],&buf)==-1)
                     {   
                         my_error("lstat",__LINE__);
                     }
                     if(filename[i][2]!='.')
                    total=total+buf.st_blocks/2; //???
                }
           }

           if((flag&PARAM_l||flag&PARAM_s))
            {
               printf("总用量 %d\n",total);
            }


            if(flag&PARAM_r)
              {    
                  if(flag&PARAM_R) 
                    {       flag-=PARAM_R;
                            ls_R(path,flag);
                    }
                    else
                     {    flag-=PARAM_r;
                         for(int i=cnt-1;i>=0;i--)
                           {  
                           display_file(flag,filename[i]);
                           }
                     }
              }
            else
             {
                     if(flag&PARAM_R)
                      {   flag-=PARAM_R;
                          
                          ls_R(path,flag);
                          
                      }
                      else
                       {   
                           for(int i=0;i<cnt;i++)
                            {   
                            display_file(flag,filename[i]);
                            }
                       }

             }
          for(int i=0;i<cnt+1;i++)
    {
      free(filename[i]);
    }
    free(filename);
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Linux 系统中,`ls -l` 命令可以列出指定目录下的文件以及文件的详细信息,包括文件权限、文件类型、文件所有者、文件大小、修改时间等。下面我们来仿写一个类似的 Python 脚本,实现Linux 系统下使用 Python 命令行执行类似 `python my_ls.py /path/to/dir` 命令,输出指定目录下的文件以及文件的详细信息。 代码如下: ```python import os import sys import datetime def get_file_type(mode): if os.path.isdir(mode): return 'd' elif os.path.islink(mode): return 'l' elif os.path.isfifo(mode): return 'p' elif os.path.ischr(mode): return 'c' elif os.path.isblk(mode): return 'b' elif os.path.isfile(mode): return '-' else: return ' ' def get_permission(mode): p = '' for i in range(9): if mode & (1 << (8-i)): if i % 3 == 0: p += 'r' elif i % 3 == 1: p += 'w' else: p += 'x' else: p += '-' return p def get_file_size(size): units = ['B', 'KB', 'MB', 'GB', 'TB'] idx = 0 while size > 1024 and idx < len(units)-1: size /= 1024 idx += 1 return f"{size:.1f}{units[idx]}" def list_files(path): for root, dirs, files in os.walk(path): for name in files: file_path = os.path.join(root, name) stat = os.stat(file_path) mode = stat.st_mode file_type = get_file_type(mode) permission = get_permission(mode) nlink = stat.st_nlink user = os.getpwuid(stat.st_uid).pw_name group = os.getgrgid(stat.st_gid).gr_name size = get_file_size(stat.st_size) mtime = datetime.datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S') print(f"{file_type}{permission} {nlink:>2} {user:<10} {group:<10} {size:>6} {mtime} {name}") if __name__ == '__main__': if len(sys.argv) != 2: print("Usage: python my_ls.py <path>") sys.exit(1) path = sys.argv[1] if not os.path.exists(path): print(f"{path} does not exist") sys.exit(1) list_files(path) ``` 代码解释: - `get_file_type(mode)`:根据文件的 `mode` 属性获取文件类型,返回类型的简写字符。如果不是已知类型,则返回空格。 - `get_permission(mode)`:根据文件的 `mode` 属性获取文件的权限,返回如 `-rw-r--r--` 的字符串。 - `get_file_size(size)`:将文件大小转换成合适的单位,返回如 `1.2KB` 的字符串。 - `list_files(path)`:遍历指定目录下的所有文件,输出文件信息。其中,使用 `os.stat` 函数获取文件的详细信息,然后根据需求使用上述函数获取需要的信息。 运行示例: ``` $ python my_ls.py /home/ drwxr-xr-x 26 root root 4.0K 2021-06-27 14:25:18 root drwxr-xr-x 3 bin bin 4.0K 2021-06-27 14:24:45 bin drwxr-xr-x 3 daemon daemon 4.0K 2021-06-27 14:24:45 daemon drwxr-xr-x 3 messagebus messagebus 4.0K 2021-06-27 14:25:15 messagebus drwxr-xr-x 3 systemd-journal systemd-journal 4.0K 2021-06-27 14:24:45 systemd-journal drwxr-xr-x 2 nobody nogroup 4.0K 2021-06-27 14:24:43 nobody drwxr-xr-x 3 syslog syslog 4.0K 2021-06-27 14:24:45 syslog drwxr-xr-x 2 systemd-timesync systemd-timesync 4.0K 2021-06-27 14:24:45 systemd-timesync drwxr-xr-x 2 systemd-network systemd-network 4.0K 2021-06-27 14:24:45 systemd-network drwxr-xr-x 2 polkitd polkitd 4.0K 2021-06-27 14:25:15 polkitd drwxr-xr-x 2 sshd sshd 4.0K 2021-06-27 14:25:15 sshd drwxr-xr-x 2 systemd-resolve systemd-resolve 4.0K 2021-06-27 14:24:45 systemd-resolve drwxr-xr-x 2 lp lp 4.0K 2021-06-27 14:25:15 lp drwxr-xr-x 2 avahi avahi 4.0K 2021-06-27 14:24:45 avahi drwxr-xr-x 2 colord colord 4.0K 2021-06-27 14:25:15 colord drwxr-xr-x 2 usbmux usbmux 4.0K 2021-06-27 14:25:15 usbmux drwxr-xr-x 2 lightdm lightdm 4.0K 2021-06-27 14:25:15 lightdm drwxr-xr-x 2 gdm gdm 4.0K 2021-06-27 14:24:45 gdm drwxr-xr-x 2 rtkit rtkit 4.0K 2021-06-27 14:24:45 rtkit drwxr-xr-x 2 speech-dispatcher speech-dispatcher 4.0K 2021-06-27 14:24:45 speech-dispatcher drwxr-xr-x 2 ntp ntp 4.0K 2021-06-27 14:24:45 ntp drwxr-xr-x 2 statd statd 4.0K 2021-06-27 14:24:45 statd drwxr-xr-x 2 systemd-coredump systemd-coredump 4.0K 2021-06-27 14:24:45 systemd-coredump drwxr-xr-x 2 kernoops kernoops 4.0K 2021-06-27 14:24:45 kernoops drwxr-xr-x 2 uuidd uuidd 4.0K 2021-06-27 14:24:45 uuidd drwxr-xr-x 2 tss tss 4.0K 2021-06-27 14:24:45 tss ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值