==============================================================================================================================================================================
作者:心梦无痕
完成时间2013 .7 .26
程序主体思路来自,linuxc 编程实战 自己实现ls
find(); 除外
分析原代碼的一些感悟,该程序将命令行中的参数转化为宏(以数字替换)
--1.#define PARAM_NONE 0 在main函数中,int flag=PARAM_NONE ;得到flag时,
通过判断,参数赋值给flag
flag|=(定义过该代表命令的宏)
有 0|x==x;
获得命令参数标志
如有多个选项直接讨论他们相加的情况,避免了直接对,选项名的讨论。
--2.定义了每一行容纳长度的宏
当前行的占用长度,以此作为衡量尺度判断,该文件名应该放到该行还是下一行。
再问件名间打印固定的空格数,(也可定义为宏);
如果使用固定个数打印,如果某行文件名较长的话,就不能显示全文件名;
然而该方法会自动将其放到下一行打印
=============================================================================================================================================================================
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <string.h>
#define PARAM_NONE 0 //无参数
#define PARAM_A 1 //-a
#define PARAM_L 2 //-l
#define PARAM_R 10
#define MAXROWLEN 80//一行显示的最多字数
int sys_leave=MAXROWLEN;
int sys_maxlen;
void show_attribute(struct stat buf,char* filename);
void display(int flag,char* pathname);
void show_ruler(char *);
void find_all(char* dirnamex)
{
DIR * dir=NULL;
char dirname[1024];
char dirlist[256][1204];
struct dirent * ptr;
struct stat st;
int i=0,j=0;
char path1[512];
puts(dirnamex);
chdir(dirnamex);
getwd(dirname);
printf("dir:%s\n",dirname);
if((dir=opendir("./"))==NULL)
{
printf("null");
return ;
}
i=0;
while((ptr=readdir(dir))!=NULL)
{
if(stat(ptr->d_name,&st)==-1)
{
perror("error name");
}
if(strcmp(ptr->d_name,".")&&strcmp(ptr->d_name,".."))
{
//puts(ptr->d_name);
show_ruler(ptr->d_name);
if(S_ISDIR(st.st_mode))
{
strcpy(dirlist[i++],ptr->d_name);
}
}
}
for(j=0;j<i;j++)
{
find_all(dirlist[j]);
}
//回到上层目录,将其设置为工作目录
chdir("..");
}
void display_dir(int flag,char* path)
{
DIR* dir;
struct dirent* ptr;
int count;
char filename[256][PATH_MAX+1],temp[PATH_MAX+1];
int i,j,len;
dir=opendir(path);
if(dir==NULL)
{
exit(1);
}
while((ptr=readdir(dir))!=NULL)
{
if(sys_maxlen<strlen(ptr->d_name))
sys_maxlen=strlen(ptr->d_name);
count++;
}
closedir(dir);
if(count>256)
{
printf("too lage\n");
exit(1);
}
len=strlen(path);
dir=opendir(path);
for(i=0;i<count;i++)
{
ptr=readdir(dir);
if(ptr==NULL)
{
printf("readdir\n");
exit(1);
}
strncpy(filename[i],path,len);
filename[i][len]='\0';
strcat(filename[i],ptr->d_name);
filename[i][strlen(ptr->d_name)+len]='\0';
}
for(i=0;i<count-1;i++)
{
for(j=0;j<count-1-i;j++)
{
if(strcmp(filename[j],filename[j+1])>0)
{
strcpy(temp,filename[j+1]);
temp[strlen(filename[j+1])]='\0';
strcpy(filename[j+1],filename[j]);
filename[j+1][strlen(filename[j])]='\0';
strcpy(filename[j],temp);
filename[j][strlen(temp)]='\0';
}
}
}
for(i=0;i<count;i++)
{
display(flag,filename[i]);
}
closedir(dir);
if((flag&PARAM_L)==0)
printf("\n");
}
void show_error(char* errorcase,int len)
{
fprintf(stderr,"len:%d",len);
perror(errorcase);
exit(1);
}
void show_ruler(char* filename)
{
int i,len;
if(sys_leave<sys_maxlen)
{
//新行开始,预留回复
printf("\n");
sys_leave=MAXROWLEN;
}
//获得长度
len=strlen(filename);
//获得空格数
len=sys_maxlen-len;
printf("%-s",filename);
for(i=0;i<len;i++)
{
printf(" ");
}
printf(" ");
sys_leave-=sys_maxlen;
sys_leave-=2;
}
void display(int flag,char* pathname)
{
int i,j;
char filename[NAME_MAX+1];
struct stat filestat;
//for(i=0,j=0;*(pathname+i)!="\0";i++)
for(i=0,j=0;i<strlen(pathname);i++)
{
if(*(pathname+i)=='/')
{
continue;
j=0;
}
filename[j++]=*(pathname+i);
}
filename[j]='\0';
strcpy(filename,filename+1);
if(lstat(pathname,&filestat)==-1)
{
show_error("setstat",__LINE__);
}
switch(flag)
{
case PARAM_NONE:
if(filename[0]!='.')
{
show_ruler(filename);
}
break;
case PARAM_A:
show_ruler(filename);
break;
case PARAM_L:
if(filename[0]!='.')
{
show_attribute(filestat,filename);
printf(" %s\n",filename);
}
break;
case PARAM_A+PARAM_L:
{
show_attribute(filestat,filename);
printf(" %s\n",filename);
}
break;
case PARAM_R:
find_all(filename);
break;
default :
break;
}
}
void show_attribute(struct stat buf,char* filename)
{
//时间的格式位数
char buf_time[32];
struct passwd *password;
struct group *grp;
if(S_ISLNK(buf.st_mode))
{
printf("1");
}
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");
}
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("-");
}
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_IRGRP){
printf("x");
}else{
printf("-");
}
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(" ");
password=getpwuid(buf.st_uid);
grp=getgrgid(buf.st_gid);
printf("M",(int)buf.st_nlink);
printf("%-8s",password->pw_name);
printf("%-8s",grp->gr_name);
printf("m",(int)buf.st_size);
strcpy(buf_time,ctime(&buf.st_mtime));
buf_time[strlen(buf_time)-1]='\0';
printf(" %s",buf_time);
}
void main(int argc,char** argv)
{
int i,j,k,num;
char path[PATH_MAX+1];
char param[32];
int flag_param=PARAM_NONE;
struct stat buf;
j=0;
num=0;
for(i=1;i<argc;i++){
if(argv[i][0]=='-'){
for(k=1;k<strlen(argv[i]);k++,j++){
param[j]=argv[i][k];
}
num++; //- count
}
}
for(i=0;i<j;i++)
{
if(param[i]=='a'){
flag_param|=PARAM_A;
continue;
}else if(param[i]=='l'){
flag_param|=PARAM_L;
continue;
}
else if(param[i]=='R')
{
flag_param|=PARAM_R;
}
else
{
printf("my ls :invalid option %c\n",param[i]);
exit(1);
}
}
param[j]='\0';
if(num+1==argc)
{
strcpy(path,"./");
path[2]='\0';
display_dir(flag_param,path);
return;
}
i=1;
do{
if(argv[i][0]=='-'){
i++;
continue;
}else{
strcpy(path,argv[i]);
//not dir or file showerror
if(stat(path,&buf)==-1)
{
show_error("stat",__LINE__);
}
if(S_ISDIR(buf.st_mode)){
if(path[strlen(argv[i])-1]!='/'){
path[strlen(argv[i])-1]='/';
path[strlen(argv[i])+1]='\0';
}else{
path[strlen(argv[i])]='\0';
}
display_dir(flag_param,path);
i++;
}
else {
display(flag_param,path);
i++;
}
}
}while(i<argc);
}