ls是Linux上经常使用的一个命令,它的参数也比较多,在此仅实现了-a,-A,-s,-l和-R以及这几个参数混合使用的情况,先上代码:
源代码:
#include<stdio.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<dirent.h>
#include<unistd.h>
#define cmd_path "./ls" //ls为gcc编译时用-o参数设置的可执行文件名
void for_R(int cou,char **cho);
struct file
{
long block;
char name[256];
char perm[10];
char style;
int nlink;
char user[20];
char group[20];
long long size;
char mtime[25];
};
struct prarm
{
char path[10][300];
int prarm_flag;
};
int pro_a=0x01;
int pro_A=0x02;
int pro_l=0x04;
int pro_R=0x08;
int pro_s=0x10;
char PRO_a[10]="all";
char PRO_A[20]="almost -all";
int analyse(int argc,char *argv) //解析单个参数或选项
{
int ret=0;
if(argv[0]!='-') return -1; //不是参数,可能是文件名或路径
if(argv[1]=='-')
{
if(!(strcmp(argv+2,PRO_a))) return pro_a;
if(!(strcmp(argv+2,PRO_A))) return pro_A;
return 0;
}
while(*argv++) //解析参数
{
switch(*argv) //混合参数一并处理
{
case 'a': ret|=pro_a;break;
case 'A': ret|=pro_A;break;
case 'l': ret|=pro_l;break;
case 'R': ret|=pro_R;break;
case 's': ret|=pro_s;break;
}
}
return ret;
}
void getperm(int i,struct file *list,struct stat list_t) //获得文件权限
{
char str[10]={'-','-','-','-','-','-','-','-','-','\0'};
mode_t mode=list_t.st_mode;
str[0]=(mode&S_IRUSR)? 'r':'-';
str[1]=(mode&S_IWUSR)? 'w':'-';
str[2]=(mode&S_IXUSR)? 'x':'-';
str[3]=(mode&S_IRGRP)? 'r':'-';
str[4]=(mode&S_IWGRP)? 'w':'-';
str[5]=(mode&S_IXGRP)? 'x':'-';
str[6]=(mode&S_IROTH)? 'r':'-';
str[7]=(mode&S_IWOTH)? 'w':'-';
str[8]=(mode&S_IXOTH)? 'x':'-';
strcpy(list[i].perm,str);
}
void sort(int sum,struct file *list) //按ASCII码排序
{
struct file t;
for(int i=0;i<sum;i++)
for(int j=0;j<sum-i-1;j++)
if(strcmp(list[j].name,list[j+1].name)>0)
{t=list[j];list[j]=list[j+1];list[j+1]=t;}
}
void get_infor(int i,struct file *list,struct stat list_t) //获取文件信息
{
if(S_ISREG(list_t.st_mode)) list[i].style='-'; //判断文件类型
else if(S_ISDIR(list_t.st_mode)) list[i].style='d';
else if(S_ISCHR(list_t.st_mode)) list[i].style='c';
else if(S_ISBLK(list_t.st_mode)) list[i].style='b';
else if(S_ISLNK(list_t.st_mode)) list[i].style='l';
else if(S_ISFIFO(list_t.st_mode)) list[i].style='p';
else if(S_ISSOCK(list_t.st_mode)) list[i].style='s';
else list[i].style='?';
getperm(i,list,list_t); //获取文件权限
list[i].nlink=list_t.st_nlink;
list[i].size=(long long)list_t.st_size;
(list[i].size%4096==0)? list[i].block=(list[i].size/1024):(list[i].block=((list[i].size/4096)+1)*4);
strcpy(list[i].mtime,ctime(&list_t.st_mtime)); //获取文件的mtime
list[i].mtime[strlen(list[i].mtime)-9]='\0'; //格式化文件的mtime
strcpy(list[i].mtime,list[i].mtime+4);
if(getpwuid(list_t.st_uid)==NULL) strcpy(list[i].user,"");
else
strcpy(list[i].user,getpwuid(list_t.st_uid)->pw_name);
if(getgrgid(list_t.st_gid)==NULL) strcpy(list[i].group,"");
else
strcpy(list[i].group,getgrgid(list_t.st_gid)->gr_name);
}
int creat_fileline(struct file *list,struct prarm ret,int i,int *exist) //创建文件列表
{
struct stat list_t;
DIR *p;char path[300];
struct dirent *pt;
int file_sum=0;
if((p=opendir(ret.path[i]))==NULL) //可能不存在或是文件名
{
*exist=1;
p=opendir("./");int flag=0;
ret.path[i][strlen(ret.path[i])-1]='\0';
while((pt=readdir(p))!=NULL)
{
if(!(strcmp(ret.path[i],pt->d_name)))
{
strcpy(list[file_sum].name,pt->d_name);
strcpy(path,ret.path[i]);
lstat(path,&list_t);
get_infor(file_sum,list,list_t);
file_sum++;
flag=1;break;
}
} if(!(flag)) printf("ls:no such file or directory!!\n");
strcat(ret.path[i],"/");
}
else
{
while((pt=readdir(p))!=NULL)
{
strcpy(list[file_sum].name,pt->d_name);
strcpy(path,ret.path[i]);
strcat(path,pt->d_name);
lstat(path,&list_t);
get_infor(file_sum,list,list_t);
file_sum++;
}
sort(file_sum,list);
}closedir(p);
return file_sum;
}
struct prarm set_prarm(int *sum,int argc,char *argv[]) //解析命令所带的参数
{
struct prarm ret;
if(argv[1]==NULL) //没有参数和路径,以./为默认路径
{
(*sum)++;
strcpy(ret.path[0],"./");
}
ret.prarm_flag=0;
for(int i=1;i<argc;++i)
{
int t=analyse(argc,argv[i]); //逐个分析参数或选项
if(t==-1) {strcpy(ret.path[*sum],argv[i]);(*sum)++;}
else ret.prarm_flag|=t;
}
if(*sum==0) {(*sum)++;strcpy(ret.path[0],"./");}
return ret;
}
void output(int *sum,struct file *list,int file_sum,struct prarm ret,int i,int *exist)
{
float nsize_sum=0; //输出列表中的文件的总大小(KB)
int c=3;char *cmd[4];
for(int k=0;k<3;k++) cmd[k]=(char *)malloc(sizeof(char *)*100);
switch(ret.prarm_flag)
{
case 0: case 16: //-无参 (s)
if(*sum>=2&&(!(*exist))) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||list[i].name[0]=='.'){}
else {
if(ret.prarm_flag==16) printf("%3ld ",list[i].block);
printf("%-6s ",list[i].name);
}
}printf("\n");
break;
case 1:case 3:case 17:case 19: //-a(s) -aA(s)
if(*sum>=2&&(!(*exist))) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(ret.prarm_flag==16) printf("%3ld ",list[i].block);
printf("%-6s ",list[i].name);
}printf("\n");
break;
case 2:case 18: //-A(s)
if(*sum>=2&&(!(*exist))) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||!strcmp(list[i].name,".")){}
else{
if(ret.prarm_flag==16) printf("%3ld ",list[i].block);
printf("%-6s ",list[i].name);
}
}printf("\n");
break;
case 4:case 20: //-l(s)
if(*sum>=2&&(!(*exist))) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(list[i].style=='l'||!(strcmp(list[i].name,".."))||list[i].name[0]=='.'){}
else nsize_sum+=list[i].block;
}
if(!(*exist))
printf("total %.0f\n",nsize_sum);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||list[i].name[0]=='.'){}
else{
if(ret.prarm_flag==20) printf("%3ld ",list[i].block);
printf("%c%s%6d %-7s%-7s%6lld %s %s\n",list[i].style,list[i].perm,list[i].nlink,
list[i].user,list[i].group,list[i].size,list[i].mtime,list[i].name);
}
}printf("\n");
break;
case 6:case 22: //-Al(s)
if(*sum>=2&&(!(*exist))) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(list[i].style=='l'||!(strcmp(list[i].name,".."))||!(strcmp(list[i].name,"."))){}
else nsize_sum+=list[i].block;
}
if(!(*exist))
printf("total %.0f\n",nsize_sum);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||!(strcmp(list[i].name,"."))){}
else {
if(ret.prarm_flag==22) printf("%3ld ",list[i].block);
printf("%c%s%6d %-7s%-7s%6lld %s %s\n",list[i].style,list[i].perm,list[i].nlink,
list[i].user,list[i].group,list[i].size,list[i].mtime,list[i].name);
}
}printf("\n");
break;
case 5:case 7: case 21:case 23://-al(s) -aAl(s)
if(*sum>=2&&(!(*exist))) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(list[i].style=='l'){}
else nsize_sum+=list[i].block;
}
if(!(*exist))
printf("total %.0f\n",nsize_sum);
for(int i=0;i<file_sum;++i)
{
if(ret.prarm_flag==21||ret.prarm_flag==23) printf("%3ld ",list[i].block);
printf("%c%s%6d %-7s%-7s%6lld %s %s\n",list[i].style,list[i].perm,list[i].nlink,
list[i].user,list[i].group,list[i].size,list[i].mtime,list[i].name);
}printf("\n");
break;
case 8: case 24: //-R(s)
if(!(*exist)) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||list[i].name[0]=='.'){}
else{
if(ret.prarm_flag==24) printf("%3ld ",list[i].block);
printf("%s ",list[i].name);
}
}printf("\n");
for(int j=0;j<file_sum;++j)
{
if(list[j].style=='d'&&strcmp(list[j].name,"..")&&strcmp(list[j].name,"."))
{
if(ret.path[i][strlen(ret.path[i])-1]!='/') strcat(ret.path[i],"/");
strcat(ret.path[i],list[j].name);
strcpy(cmd[0],cmd_path);
if(ret.prarm_flag==24) strcpy(cmd[1],"-sR");else strcpy(cmd[1],"-R");
strcpy(cmd[2],ret.path[i]);
for_R(c,cmd);
}
char *p=strrchr(ret.path[i],'/');
*(p+1)='\0';
}
break;
case 10:case 26: //-AR(s)
if(!(*exist)) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||!strcmp(list[i].name,".")){}
else{
if(ret.prarm_flag==26) printf("%3ld ",list[i].block);
printf("%s ",list[i].name);
}
}printf("\n");
for(int j=0;j<file_sum;++j)
{
if(list[j].style=='d'&&strcmp(list[j].name,"..")&&strcmp(list[j].name,"."))
{
if(ret.path[i][strlen(ret.path[i])-1]!='/') strcat(ret.path[i],"/");
strcat(ret.path[i],list[j].name);
strcpy(cmd[0],cmd_path);
if(ret.prarm_flag==26)
strcpy(cmd[1],"-sAR");
else strcpy(cmd[1],"-AR");
strcpy(cmd[2],ret.path[i]);
for_R(c,cmd);
}
char *p=strrchr(ret.path[i],'/');
*(p+1)='\0';
}
break;
case 9:case 11:case 25:case 27: //-aR(s) -aAR(s)
if(!(*exist)) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(ret.prarm_flag==25||ret.prarm_flag==27) printf("%3ld ",list[i].block);
printf("%s ",list[i].name);
}printf("\n");
for(int j=0;j<file_sum;++j)
{
if(list[j].style=='d'&&strcmp(list[j].name,"..")&&strcmp(list[j].name,"."))
{
if(ret.path[i][strlen(ret.path[i])-1]!='/') strcat(ret.path[i],"/");
strcat(ret.path[i],list[j].name);
strcpy(cmd[0],cmd_path);
if(ret.prarm_flag==25||ret.prarm_flag==27)
strcpy(cmd[1],"-saR");
else strcpy(cmd[1],"-aR");
strcpy(cmd[2],ret.path[i]);
for_R(c,cmd);
}
char *p=strrchr(ret.path[i],'/');
*(p+1)='\0';
}
break;
case 12:case 28: //-lR(s)
if(!(*exist)) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(list[i].style=='l'||!(strcmp(list[i].name,".."))||list[i].name[0]=='.'){}
else nsize_sum+=list[i].block;
}
if(!(*exist))
printf("total %.0f\n",nsize_sum);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||list[i].name[0]=='.'){}
else{
if(ret.prarm_flag==28) printf("%3ld ",list[i].block);
printf("%c%s%6d %-7s%-7s%6lld %s %s\n",list[i].style,list[i].perm,list[i].nlink,
list[i].user,list[i].group,list[i].size,list[i].mtime,list[i].name);
}
}printf("\n");
for(int j=0;j<file_sum;++j)
{
if(list[j].style=='d'&&strcmp(list[j].name,"..")&&strcmp(list[j].name,"."))
{
if(ret.path[i][strlen(ret.path[i])-1]!='/') strcat(ret.path[i],"/");
strcat(ret.path[i],list[j].name);
strcpy(cmd[0],cmd_path);
if(ret.prarm_flag==28)
strcpy(cmd[1],"-lsR");
else strcpy(cmd[1],"-lR");
strcpy(cmd[2],ret.path[i]);
for_R(c,cmd);
}
char *p=strrchr(ret.path[i],'/');
*(p+1)='\0';
}
break;
case 14: case 30: //-ARl(s)
if(!(*exist)) printf("%s:\n",ret.path[i]);
for(int i=0;i<file_sum;++i)
{
if(list[i].style=='l'||!(strcmp(list[i].name,".."))||!(strcmp(list[i].name,"."))){}
else nsize_sum+=list[i].block;
}
if(!(*exist))
printf("total %.0f\n",nsize_sum);
for(int i=0;i<file_sum;++i)
{
if(!(strcmp(list[i].name,".."))||!(strcmp(list[i].name,"."))){}
else{
if(ret.prarm_flag==30) printf("%3ld ",list[i].block);
printf("%c%s%6d %-7s%-7s%6lld %s %s\n",list[i].style,list[i].perm,list[i].nlink,
list[i].user,list[i].group,list[i].size,list[i].mtime,list[i].name);
}
}printf("\n");
for(int j=0;j<file_sum;++j)
{
if(list[j].style=='d'&&strcmp(list[j].name,"..")&&strcmp(list[j].name,"."))
{
if(ret.path[i][strlen(ret.path[i])-1]!='/') strcat(ret.path[i],"/");
strcat(ret.path[i],list[j].name);
strcpy(cmd[0],cmd_path);
if(ret.prarm_flag==30)
strcpy(cmd[1],"-sARl");
else strcpy(cmd[1],"-ARl");
strcpy(cmd[2],ret.path[i]);
for_R(c,cmd);
}
char *p=strrchr(ret.path[i],'/');
*(p+1)='\0';
}
break;
case 13:case 15:case 29:case 31://-aRl(s) -aARl(s)
if(!(*exist)) printf("%s:\n",ret.path[i]); //若不是文件则打印路径
for(int i=0;i<file_sum;++i)
{
if(list[i].style=='l'){}
else nsize_sum+=list[i].block;
}
if(!(*exist))
printf("total %.0f\n",nsize_sum);
for(int i=0;i<file_sum;++i)
{
if(ret.prarm_flag==29||ret.prarm_flag==31) printf("%3ld ",list[i].block);
printf("%c%s%6d %-7s%-7s%6lld %s %s\n",list[i].style,list[i].perm,list[i].nlink,
list[i].user,list[i].group,list[i].size,list[i].mtime,list[i].name);
}printf("\n");
for(int j=0;j<file_sum;++j)
{
if(list[j].style=='d'&&strcmp(list[j].name,"..")&&strcmp(list[j].name,"."))
{
if(ret.path[i][strlen(ret.path[i])-1]!='/') strcat(ret.path[i],"/");
strcat(ret.path[i],list[j].name);
strcpy(cmd[0],cmd_path);
if(ret.prarm_flag==29||ret.prarm_flag==31)
strcpy(cmd[1],"-salR");
else strcpy(cmd[1],"-alR");
strcpy(cmd[2],ret.path[i]);
for_R(c,cmd);
}
char *p=strrchr(ret.path[i],'/'); //若当前目录下无目录即递归完成,回到上一层目录
*(p+1)='\0';
}
break;
}
}
void for_R(int cou,char **cho) //用作-R参数 的递归调用
{
struct file *list=(struct file*)malloc(sizeof(struct file)*10000);
int sum=0,file_sum=0,exist=0;
struct prarm ret=set_prarm(&sum,cou,cho);
for(int i=0;i<sum;++i)
{
int len=strlen(ret.path[i]);
if(ret.path[i][len-1]!='/') {strcat(ret.path[i],"/");}
}
for(int i=0;i<sum;++i)
{
file_sum=creat_fileline(list,ret,i,&exist);
output(&sum,list,file_sum,ret,i,&exist);
exist=0;
}
free(list);
}
int main(int argc,char *argv[])
{
struct file *list=(struct file*)malloc(sizeof(struct file)*10000);
int sum=0,file_sum=0,exist=0; //sum,待处理路径的数目,file_sum文件列表中文件的数目,exist判断是否为文件名
struct prarm ret=set_prarm(&sum,argc,argv); //ret记录每一个路径或文件名,记录参数
for(int i=0;i<sum;++i)
{
int len=strlen(ret.path[i]);
if(ret.path[i][len-1]!='/') {strcat(ret.path[i],"/");}
}
for(int i=0;i<sum;++i)
{
file_sum=creat_fileline(list,ret,i,&exist); //创建文件列表
output(&sum,list,file_sum,ret,i,&exist);
exist=0;
}
return 0;
}
运行结果:
可见此程序:
1、可以处理单个参数(-a)或是混合参数(-lR);
2、支持多路径或是路径与文件名的混合;
3、对于多路径的情况分别打印出了当前的路径名并且各个路径之间也以空行隔开;
4、对于每个目录也都统计了所占空间的大小(KB)。
问题:
emmm,虽然上图看起来比较整齐,但实际上此程序中:
1、并没有列对齐的部分,若文件名较长的话排版会显得很乱。
2、显而易见,对于特殊文件是没有高亮显示的
该程序虽然可以处理文件名的情况,但仅限于当前目录下,下一层目录下的文件名并不会处理。对于多参数,只在其中寻找合法参数,不合法参数没有处理。