QQ登录

只需一步,快速开始

登录 | 立即注册 | 找回密码

熊天琪游戏论坛 - 玩出名堂

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 13|回复: 0

[文本教程] Linux下ls命令的实现

[复制链接]
发表于 2018-10-10 02:13:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
实现Linux下的ls命令,网上的代码总是不是太完善。主要实现ls, ls -l两个功能。分栏排序不是很满意,linux原版分栏简直赞,对齐的十分完美。这个代码是在网上的基础上改bug和修改完成。
代码更新在https://github.com/ljfly/ls
主要函数void do_ls( int,char [] );void dostat( char * ); /*get file info*/void show_file_info( char *,struct stat * ); //ls -l 的输出void display_Ls( int cnt ) // ls 的分栏输出void mode_to_letters( int,char [] ); //文件属性: drwxr-xr-xchar *uid_to_name( uid_t ); /* 通过 uid 获得对应的用户名 */char *gid_to_name( gid_t ); /* 通过 gid 获得对应的组名 */void getcolor( char * ); //获取压缩颜色int get_file_type( char * ); /*get file type*/int get_modify_time( char * ); /*get file last modify time*/void getWidth(); //获取屏幕宽度
#include<stdio.h>#include<string.h>#include<stdlib.h>#include<sys/types.h>#include<sys/stat.h>#include<sys/ioctl.h>#include<dirent.h>#include<pwd.h>#include<grp.h>#include<unistd.h>
/*head file*/
#define LenOfName 256#define maxN 1005#define maxM 505#define maxL 105#define LenOfPath 256<<4#define LS 0   //ls#define LS_A 1  //ls -a#define LS_L 2  //ls -l#define LS_TMP 3 //ls /tmp#define LS_T 5  //ls -t/*define file*/
void do_ls( int,char [] );void dostat( char * );                   /*get file info*/void show_file_info( char *,struct stat * ); //ls -l 的输出void mode_to_letters( int,char [] );      //文件属性:drwxr-xr-xchar *uid_to_name( uid_t );        /* 通过uid获得对应的用户名 */char *gid_to_name( gid_t );       /* 通过gid获得对应的组名 */void getcolor( char * );           int get_file_type( char * );       /*get file type*/int get_modify_time( char * );     /*get file last modify time*/void getWidth();int cmp1( const void * ,const void * );  //文件名排序 int cmp2( const void * ,const void * );  //文件修改时间排序
struct outputFile{  char FileName[ LenOfName ];  int modify_time ;   int file_type ;}Output[ maxN ],OutputPoint[ maxM ],Temp[ maxN+maxM ];int colormode,foreground,background;int terminalWidth ;
void dostat( char *filename ){  struct stat info;  if( stat( filename,&info )==-1 ){    perror( filename );    printf("filename:%s\n", filename);  }  else{    char *pname = strrchr(filename, '/');    getcolor(filename );    show_file_info( pname+1,&info );  }  return ;}/*get file info*/
void mode_to_letters( 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( 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';    return ;}
char *uid_to_name( uid_t uid ){  struct passwd *pw_ptr;  static char numstr[ 10 ];  if( (pw_ptr = getpwuid( uid ) )==NULL ){    sprintf(numstr,"%d",uid);    return numstr;  }  else{    return pw_ptr->pw_name;  }}
/* 通过uid获得对应的用户名 */
char *gid_to_name( gid_t gid ){  struct group *grp_ptr;  static char numstr[ 10 ];  if( (grp_ptr = getgrgid( gid ) )==NULL ){    sprintf(numstr,"%d",gid);    return numstr;  }  else{    return grp_ptr->gr_name;  }}/* 通过gid获得对应的组名 */
int get_file_type( char *filename ){  struct stat info;  stat( filename,&info );  int file_type = 0;  file_type = info.st_mode & S_IFMT;  return file_type;}/*get file type*/
int get_modify_time( char *filename ){  struct stat info;  stat( filename,&info );  int modify_time = 0;  modify_time = info.st_mtime;  return modify_time;}/*get file last modify time*/
int isadir(char *str){  struct stat info;  return ( lstat(str,&info) != -1 && S_ISDIR(info.st_mode) );}/*判断某文件是否为目录文件*/

void getWidth(){  char *tp;  struct winsize wbuf;  terminalWidth = 80;  if( isatty(STDOUT_FILENO) ){     if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &wbuf) == -1 || wbuf.ws_col == 0){      if( tp = getenv("COLUMNS") )        terminalWidth = atoi( tp );    }    else      terminalWidth = wbuf.ws_col;  }  return ;}/******************************************************************  得出终端的宽度,默认宽度为80,如果获取失败,将激活-1选项*******************************************************************/

int cmp1( const void *p ,const void *q ){  char T1[ LenOfName ],T2[ LenOfName ];  strcpy( T1,(*(struct outputFile *)p).FileName );  strcpy( T2,(*(struct outputFile *)q).FileName );  int len1 = strlen( T1 );  int i ;  for( i=0;i<len1;i++ ){    if( T1[ i ]>='A' && T1[ i ]<='Z' ){      T1[ i ] = T1[ i ] - 'A' + 'a';    }  }  int len2 = strlen( T2 );  for( i=0;i<len2;i++ ){    if( T2[ i ]>='A' && T2[ i ]<='Z' ){      T2[ i ] = T2[ i ] - 'A' + 'a';    }  }  return strcmp( T1,T2 );}/********************************************************  文件名排序 cmp1*********************************************************/
int cmp2( const void *p,const void *q ){  return (*(struct outputFile *)p).modify_time < (*(struct outputFile *)q).modify_time ;}/********************************************************  文件修改时间排序 cmp2*********************************************************/
void show_file_info( char *filename,struct stat * info_p ){  char modestr[ 12 ];    mode_to_letters( info_p->st_mode,modestr );    printf("%s",modestr);  printf("%3d ",(int)info_p->st_nlink);  printf("%-2s ",uid_to_name(info_p->st_uid));  printf("%-1s ",gid_to_name(info_p->st_gid));  printf("%7ld ",(long)info_p->st_size);  printf("%.12s ",4+ctime(&info_p->st_mtime));  printf("\033[%d;%d;%dm%s\033[0m\n",colormode,foreground,background,filename);  return ;}/*******************************************************      ls -l 的输出********************************************************/

void getcolor( char *filename ){  struct stat info;  stat( filename,&info );  foreground = 30;  background = 1;  colormode = 0;  switch ( (info.st_mode & S_IFMT) ){    case S_IFREG:        /*regular 普通文件 , 色*/      foreground = 30;      colormode = 1;      break;    case S_IFLNK:        /*symbolic link 链接文件 , 青蓝色*/      foreground = 36;      colormode = 1;      break;    case S_IFSOCK:       /*紫红色*/       foreground = 35;      colormode = 1;      break;    case S_IFDIR:        /*directory 目录文件 , 蓝色*/      foreground = 34;      break;    case S_IFBLK:        /*block special 块设备文件 , 黄色*/      foreground = 33;      colormode = 1;      break;    case S_IFCHR:        /*character special 字符设备文件 , 黄色*/      foreground = 33;      colormode = 1;      break;    case S_IFIFO:        /*fifo 绿色*/      foreground = 32;      colormode = 1;      break;  }}/*******************************************************      给文件添加颜色********************************************************/
void display_Ls( int cnt ){  int wordLenMax = 0;//the LenMax word  int wordRowNum = 0;//the amount of one row  int wordColNum = 0;//the amount of one col  int i , j;  for( i=0;i<cnt;i++ ){    if( i==0 ) wordLenMax = strlen( Output[ i ].FileName );    else wordLenMax = wordLenMax>strlen( Output[ i ].FileName )?wordLenMax:strlen( Output[ i ].FileName );  }  wordLenMax +=2;  wordRowNum = terminalWidth / wordLenMax;  if( cnt%wordRowNum==0 ) wordColNum = cnt / wordRowNum;  else wordColNum = cnt / wordRowNum + 1;  for( i=0;i<wordColNum;i++ ){    j = i;    while( j<cnt ){      getcolor( Output[ j ].FileName );      printf("\033[%d;%d;%dm%-15s\033[0m ",colormode,foreground,background,Output[ j ].FileName);      j += wordColNum;    }    printf("\n");  }  return ;}  /**********************************************************      ls的分栏输出***********************************************************/

void display_Ls_a( int cntPoint,int cnt ){  int CNT = 0;  int wordLenMax = 0;//the LenMax word  int wordRowNum = 0;//the amount of one row  int wordColNum = 0;//the amount of one col  int i , j;  for( i=0;i<cntPoint;i++ ){    strcpy( Temp[ CNT ].FileName,OutputPoint[ i ].FileName );    Temp[ CNT ].file_type = OutputPoint[ i ].file_type;    Temp[ CNT ].modify_time = OutputPoint[ i ].modify_time;    CNT ++;    wordLenMax = wordLenMax>strlen( OutputPoint[ i ].FileName )?wordLenMax:strlen( OutputPoint[ i ].FileName );  }  for( i=0;i<cnt;i++ ){    strcpy( Temp[ CNT ].FileName,Output[ i ].FileName );    Temp[ CNT ].file_type = Output[ i ].file_type;    Temp[ CNT ].modify_time = Output[ i ].modify_time;    CNT ++;    wordLenMax = wordLenMax>strlen( Output[ i ].FileName )?wordLenMax:strlen( Output[ i ].FileName );  }  wordLenMax += 2;  wordRowNum = terminalWidth / wordLenMax;  if( CNT%wordRowNum==0 ) wordColNum = CNT / wordRowNum;  else wordColNum = CNT / wordRowNum + 1;  for( i=0;i<wordColNum;i++ ){    j = i;    while( j<CNT ){      getcolor( Temp[ j ].FileName );      printf("\033[%d;%d;%dm%-15s\033[0m ",colormode,foreground,background,Temp[ j ].FileName);      j += wordColNum;    }    printf("\n");  }  return ;}/**********************************************************      ls -a 的分栏输出***********************************************************/

void display_Ls_tmp( int cnt ){  display_Ls( cnt );  return ;}/**********************************************************      ls /tmp 的分栏输出***********************************************************/
  void do_ls( int myJudge,char myOrder[] ){
  char dirname[ maxL ];  if( myJudge!=LS_TMP  && myJudge!=LS_L){    strcpy( dirname,"." );  }  else {    strcpy( dirname,myOrder );  }  DIR * dir_ptr;  struct dirent *direntp;  int cntOutput = 0;  int cntOutputPoint = 0;  char full_path[256];  if( ( dir_ptr = opendir( dirname ) )==NULL ){    fprintf( stderr,"my god, i cannot open %s\n",dirname );  }  else{    if(myJudge!=LS_L ) {        while( (direntp = readdir( dir_ptr ) )!=NULL ){      if( direntp->d_name[ 0 ]=='.' ) {        strcpy( OutputPoint[ cntOutputPoint ].FileName,direntp->d_name );        OutputPoint[ cntOutputPoint ].file_type = get_file_type( OutputPoint[ cntOutputPoint ].FileName );        OutputPoint[ cntOutputPoint ].modify_time = get_modify_time( OutputPoint[ cntOutputPoint ].FileName );        cntOutputPoint ++;      }      else {        strcpy( Output[ cntOutput ].FileName,direntp->d_name );        Output[ cntOutput ].file_type = get_file_type( Output[ cntOutput ].FileName );        Output[ cntOutput ].modify_time = get_modify_time( Output[ cntOutput ].FileName );        cntOutput ++;      }    }   }      if( myJudge==LS_T ){      qsort( OutputPoint,cntOutputPoint,sizeof( OutputPoint[0] ),cmp2 );      qsort( Output,cntOutput,sizeof( Output[0] ),cmp2 );    }    else {      qsort( OutputPoint,cntOutputPoint,sizeof( OutputPoint[0] ),cmp1 );      qsort( Output,cntOutput,sizeof( Output[0] ),cmp1 );    }    /**********************************************************      预处理输出     ***********************************************************/    if( myJudge==LS||myJudge==LS_T ){      display_Ls( cntOutput );      closedir( dir_ptr );    }    /**********************************************************      ls && ls -t    ***********************************************************/    else if( myJudge==LS_A ){      display_Ls_a( cntOutputPoint,cntOutput );      closedir( dir_ptr );    }    /**********************************************************      ls -a     ***********************************************************/    else if( myJudge==LS_L ){          while( (direntp = readdir( dir_ptr ) )!=NULL ){      if( direntp->d_name[ 0 ]=='.' ) {        strcpy( OutputPoint[ cntOutputPoint ].FileName,direntp->d_name );        OutputPoint[ cntOutputPoint ].file_type = get_file_type( OutputPoint[ cntOutputPoint ].FileName );        OutputPoint[ cntOutputPoint ].modify_time = get_modify_time( OutputPoint[ cntOutputPoint ].FileName );        cntOutputPoint ++;      }      else {        strcpy(full_path, dirname);        int dir_len = strlen(dirname);         strcpy(full_path + dir_len, direntp->d_name);        strcpy( Output[ cntOutput ].FileName,full_path );        Output[ cntOutput ].file_type = get_file_type( Output[ cntOutput ].FileName );        Output[ cntOutput ].modify_time = get_modify_time( Output[ cntOutput ].FileName );
        cntOutput ++;      }    }      int i;      for( i=0;i<cntOutput;i++ )        dostat( Output[ i ].FileName );      closedir( dir_ptr );    }    /**********************************************************      ls -l     ***********************************************************/    else {      display_Ls_tmp( cntOutput );      closedir( dir_ptr );    }    /**********************************************************      ls /tmp     ***********************************************************/  }  return ;}/*sovle*/
int main( int argc, char *argv[] ){  getWidth( );  int i ;  if( argc==1 ){    do_ls( LS,"ls" );  }  else{    int ord;    while( (ord = getopt(argc,argv,":lat"))!=-1 ){      switch( ord ){        case 'a':          do_ls( LS_A,"ls-a" );          break;        case 'l':{            if(argc == 2) do_ls( LS_L,"/" );            else {             for( i= 2;i<argc;i++ ){            if( argv[ i ][ 0 ]=='-' ) continue;            printf("%s:\n",argv[ i ]);            do_ls( LS_L,argv[ i ] );            }          }           return;        }          break;        case 't':          do_ls( LS_T,"ls-t" );          break;        default :          break;      }    }    for( i=1;i<argc;i++ ){      if( argv[ i ][ 0 ]=='-' ) continue;      printf("%s:\n",argv[ i ]);      do_ls( LS_TMP,argv[ i ] );    }  }  return 0;}/*main*/
[table=98%][/table]
熊天琪的论坛真是太好啦, 我太喜欢熊天琪啦
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Loading...

QQ|小黑屋|Archiver|手机版|熊天琪 ( 鄂ICP备14006674号,鄂公网安备42020502000003号 

安全联盟

GMT+8, 2018-10-19 13:54 , Processed in 0.097631 second(s), 27 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表