linux c模拟ls命令

/*
 模拟ls命令,实现参数-tariRl.有些代码重复出现,可改进
 可以在该程序的基础上增加参数,该程序思路清晰,容易扩展
 */

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<dirent.h>
#include<sys/ioctl.h>
#include<pwd.h>
#include<grp.h>


#define LL (1<<0)  /*带l参数标志*/
#define IL (1<<1)  /*带i参数标志*/
#define RU (1<<2)  /*带R参数标志*/
#define TL (1<<16) /*带t参数标志*/
#define AL (1<<17) /*带a参数标志*/
#define RL (1<<18) /*带r参数标志*/

#define LENGTH 500 /*字符串最大长度*/
#define MAX_FILE_COUNT 500/*文件列表最大长度*/

/*函数声明*/
void error(char* error_message,int line);
void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode);
void display_simply(char (*namelist)[LENGTH],int n);
void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_LL_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_RU(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_IL(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_IL_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);

/*主函数*/
int main(int argc,char **argv)
{
    int i,j;
    /*mode的前16个位用来标志那些能影响显示的参数,16位之后的位用来标志不影响输出格式的参数。这个程序只用到了0-3位,16-18位,如果要在该程序的基础上增加参数,可以用其他没有使用的位。
    mode的第0位为1表示带l参数,mode的第1位为1表示带i参数,mode的第2位为1表示带R参数,mode的第16位为1表示带t参数,mode的第17位为1表示带a参数,mode的第18位为1表示带r参数*/
    int mode=0;
    char error_message[LENGTH]={0};/*错误信息*/
    char path[LENGTH]={0};/*路径*/
    struct stat stalist[MAX_FILE_COUNT];/*文件详细信息数组*/
    char  namelist[MAX_FILE_COUNT][LENGTH];/*文件名数组*/
    int flag=0;/*判断是否指定了目录*/
    int count;/*文件个数*/

    /*解析参数*/
    for(i=1;i<argc;i++){
        if(argv[i][0]=='-'){/*如果是选项参数*/
	    for(j=1;j<strlen(argv[i]);j++){
		if(argv[i][j]=='l')
		    mode=mode|LL;
		else if(argv[i][j]=='i')
		    mode=mode|IL;
		else if(argv[i][j]=='R')
		    mode=mode|RU;
		else if(argv[i][j]=='r')
		    mode=mode|RL;
		else if(argv[i][j]=='a')
		    mode=mode|AL;
		else if(argv[i][j]=='t')
		    mode=mode|TL;
		else{
		    snprintf(error_message,LENGTH,"no option of %c",argv[i][j]);
		    error(error_message,__LINE__);
		}					
	    }
	}else{/*参数为目录或文件*/
	    if(flag==1)
		error("can not specify more then two dir or file",__LINE__);
	    else
		flag=1;
            if(argv[i][0]!='/'){/*相对路径*/
		strcat(path,get_current_dir_name());
		strcat(path,"/");
		strncat(path,argv[i],strlen(argv[i]));
	    }else/*绝对路径*/
		strcpy(path,argv[i]);
	}
    }

    if(flag==0)/*未指定任何目录或文件,则使用默认当前目录*/
	strcat(path,get_current_dir_name());

    /*根据mode获取指定目录下的文件*/
    count=file_list(path,stalist,namelist,mode);
    
    /*根据mode显示文件*/
    display(stalist,namelist,count,mode);

    return 0;
}


/*获取文件列表*/
int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode)
{
    int i=0,index,j,k;
    DIR *dir;
    struct dirent *ptr;
    char str[LENGTH];
    char nametemp[LENGTH];
    struct stat statemp;

    if(stat(path,&stalist[0])<0){
//	puts(path);
	error("the specify file is not exist",__LINE__);
    }
    if(S_ISDIR(stalist[0].st_mode)){/*如果该路径指向的是一个目录*/
        if((dir=opendir(path))==NULL){/*打开目录*/
	    sprintf(str,"can not open %s",path);
	    error(str,__LINE__);
	}
        chdir(path);/*改变当前工作目录到path*/
        i=0;
	while((ptr=readdir(dir))!=NULL){/*依次读取目录下的所有文件*/
	    if(ptr->d_name[0]=='.' && !(mode & AL))/*忽略隐藏文件*/
		continue;
	    /*按字母顺序插入到stalist数组及namelist数组*/
	    for(j=i;j>0;j--){
		if(strcmp(ptr->d_name,namelist[j-1])>0)
		    break;
	    }
	    for(k=i;k>j;k--){
		strcpy(namelist[k],namelist[k-1]);
		stalist[k]=stalist[k-1];
	    }

            strcpy(namelist[j],ptr->d_name);
            stat(ptr->d_name,&stalist[j]);
	    i++;
	    if(i==MAX_FILE_COUNT)
		error("file count beyond MAX_FILE_COUNT",__LINE__);
	}
	closedir(dir);
    }else{
	j=strlen(path)-1;
	while(j>=0 && path[j]!='/'){
	    j--;
	}
	if(j<0)
	    error("path error",__LINE__);
	j++;
	k=0;
        while(path[j]){
	    namelist[0][k]=path[j];
            j++;
 	    k++;
	}
        namelist[0][k]=0;
        return 1;
    }

    if(mode & TL){/*按文件修改时间排序*/
	for(j=0;j<i;j++){
	    index=j;
	    for(k=j+1;k<i;k++)
		if(stalist[index].st_mtime<stalist[k].st_mtime){
		    index=k;
		}
	    statemp=stalist[j];
	    stalist[j]=stalist[index];
	    stalist[index]=statemp;
	    strcpy(nametemp,namelist[j]);
	    strcpy(namelist[j],namelist[index]);
	    strcpy(namelist[index],nametemp);
	}
    }

    if(mode & RL){/*反序排列*/
	for(j=0;j<i/2;j++){
	    strcpy(nametemp,namelist[j]);
	    strcpy(namelist[j],namelist[i-j-1]);
	    strcpy(namelist[i-j-1],nametemp);
	    statemp=stalist[j];
	    stalist[j]=stalist[i-j-1];
	    stalist[i-j-1]=statemp;
	}
    }
    return i;
}

/*根据mode选择不同的函数进行显示*/
void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)
{
    /*使mode的高16位为0*/
    int m = mode & ((1<<16)-1);
    switch(m){
	case 0:
	    display_simply(namelist,n);
	    break;
	case 1:
	    display_LL(stalist,namelist,n);
	    break;
	case 2:
	    display_IL(stalist,namelist,n);
	    break;
	case 3:
	    display_LL_IL(stalist,namelist,n);
	    break;
	case 4:
	    display_RU(stalist,namelist,n,mode);
	    break;
	case 5:
	    display_RU_LL(stalist,namelist,n,mode);
	    break;
        case 6:
	    display_RU_IL(stalist,namelist,n,mode);
	    break;
	case 7:
	    display_RU_IL_LL(stalist,namelist,n,mode);
	    break;
    }
}

/*不带显示选项,简单显示文件名*/
void display_simply(char (*namelist)[LENGTH],int n)
{
    int i,maxlength=0,cols;
    struct winsize ts;
    for(i=0;i<n;i++)
	if(strlen(namelist[i])>maxlength)
	    maxlength=strlen(namelist[i]);
    /*获取终端的大小*/
    ioctl(STDIN_FILENO,TIOCGWINSZ,&ts);
    cols=ts.ws_col;
    cols/=(maxlength+1);
    //lines=ts.ws_row;
    for(i=0;i<n;i++){
       if(i!=0 && i%cols==0)
	   puts("");
       printf("%*s",-(maxlength+1),namelist[i]);
    }
    putchar('\n');
}

/*-l 参数,显示详细文件信息*/
void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n)
{
    int i,mode;
    char* str;
    for(i=0;i<n;i++){
        mode=stalist[i].st_mode;
        if(S_ISDIR(mode))
	    printf("d");
	else
	    printf("-");
	if(mode & (1<<8))
	    printf("r");
	else
	    printf("-");
        if(mode & (1<<7))
	    printf("w");
	else
	    printf("-");
        if(mode & (1<<6))
	    printf("x");
	else
	    printf("-");
        if(mode & (1<<5))
	    printf("r");
	else
	    printf("-");
        if(mode & (1<<4))
	    printf("w");
	else
	    printf("-");
        if(mode & (1<<3))
	    printf("x");
	else
	    printf("-");
        if(mode & (1<<2))
	    printf("r");
	else
	    printf("-");
        if(mode & (1<<1))
	    printf("w");
	else
	    printf("-");
        if(mode & (1<<0))
	    printf("x");
	else
	    printf("-");
	printf(" %-3d",stalist[i].st_nlink);
	printf(" %-6s",getpwuid(stalist[i].st_uid)->pw_name);
	printf(" %-6s",getgrgid(stalist[i].st_gid)->gr_name);
	printf(" %-10d",stalist[i].st_size);
	str=ctime(&stalist[i].st_mtime);
	str[strlen(str)-2]=0;
	printf(" %s",str);
	printf(" %s\n",namelist[i]);
    }
}

/*-i 参数,显示文件名及节点号*/
void display_IL(struct stat* stalist,char (*namelist)[LENGTH],int n)
{
    int i,maxlength=0,cols;
    struct winsize ts;
    for(i=0;i<n;i++)
	if(strlen(namelist[i])>maxlength)
	    maxlength=strlen(namelist[i]);
    /*获取终端的大小*/
    ioctl(STDIN_FILENO,TIOCGWINSZ,&ts);
    cols=ts.ws_col;
    cols/=(maxlength+9);
    //lines=ts.ws_row;
    
    for(i=0;i<n;i++){
       if(i!=0 && i%cols==0)
	   puts("");
       printf("%-8d ",stalist[i].st_ino);
       printf("%*s",-(maxlength+1),namelist[i]);
    }
    putchar('\n');   
}

/*-li 参数,显示详细文件信息和节点号*/
void display_LL_IL(struct stat * stalist,char (*namelist)[LENGTH],int n)
{
    int i,mode;
    char* str;

    for(i=0;i<n;i++){
        printf("%-8d ",stalist[i].st_ino);
        mode=stalist[i].st_mode;
        if(S_ISDIR(mode))
	    printf("d");
	else
	    printf("-");
	if(mode & (1<<8))
	    printf("r");
	else
	    printf("-");
        if(mode & (1<<7))
	    printf("w");
	else
	    printf("-");
        if(mode & (1<<6))
	    printf("x");
	else
	    printf("-");
        if(mode & (1<<5))
	    printf("r");
	else
	    printf("-");
        if(mode & (1<<4))
	    printf("w");
	else
	    printf("-");
        if(mode & (1<<3))
	    printf("x");
	else
	    printf("-");
        if(mode & (1<<2))
	    printf("r");
	else
	    printf("-");
        if(mode & (1<<1))
	    printf("w");
	else
	    printf("-");
        if(mode & (1<<0))
	    printf("x");
	else
	    printf("-");
	printf(" %-3d",stalist[i].st_nlink);
	printf(" %-6s",getpwuid(stalist[i].st_uid)->pw_name);
	printf(" %-6s",getgrgid(stalist[i].st_gid)->gr_name);
	printf(" %-10d",stalist[i].st_size);
	str=ctime(&stalist[i].st_mtime);
	str[strlen(str)-2]=0;
	printf(" %s",str);
	printf(" %s\n",namelist[i]);
	
    }

}

/*-R 参数,简单显示所有文件,包括目录下面的子目录*/
void display_RU(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];
    puts(get_current_dir_name());
    display_simply(namelist,n);
    putchar('\n');
    strcpy(path,get_current_dir_name());
    
    for(i=0;i<n;i++){
        if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
     	    continue;
	if(S_ISDIR(stalist[i].st_mode)){
	    strcpy(temp,path);
	    strcat(path,"/");
	    strcat(path,namelist[i]);
	    count=file_list(path,sta,name,mode);
	    display_RU(sta,name,count,mode);
            strcpy(path,temp);
	}
    }
}

/*-Rl 参数,显示所有文件,包括目录下面的子目录的详细信息*/
void display_RU_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];

    puts(get_current_dir_name());
    display_LL(stalist,namelist,n);
    putchar('\n');
    strcpy(path,get_current_dir_name());
    
    for(i=0;i<n;i++){
	if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
     	    continue;

	if(S_ISDIR(stalist[i].st_mode)){
	    strcpy(temp,path);
	    strcat(path,"/");
	    strcat(path,namelist[i]);
	    count=file_list(path,sta,name,mode);
	    display_RU_LL(sta,name,count,mode);
	    strcpy(path,temp);
	}
    }
}

/*-Ri 参数,简单显示所有文件,包括目录下的子目录,及节点号*/
void display_RU_IL(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];
    puts(get_current_dir_name());
    display_IL(stalist,namelist,n);
    putchar('\n');
    strcpy(path,get_current_dir_name());
    
    for(i=0;i<n;i++){
	if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
     	    continue;

	if(S_ISDIR(stalist[i].st_mode)){
	    strcpy(temp,path);
	    strcat(path,"/");
	    strcat(path,namelist[i]);
	    count=file_list(path,sta,name,mode);
	    display_RU_IL(sta,name,count,mode);
	    strcpy(path,temp);
	}
    }

}

/*-Ril 参数,显示所有文件,包括目录下面的子目录的详细信息,及节点号*/
void display_RU_IL_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];
    puts(get_current_dir_name());
    display_LL_IL(stalist,namelist,n);
    putchar('\n');
    strcpy(path,get_current_dir_name());
    
    for(i=0;i<n;i++){
	if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
     	    continue;

	if(S_ISDIR(stalist[i].st_mode)){
	    strcpy(temp,path);
	    strcat(path,"/");
	    strcat(path,namelist[i]);
	    count=file_list(path,sta,name,mode);
	    display_RU_IL_LL(sta,name,count,mode);
	    strcpy(path,temp);
	}
    }
}

//错误处理函数
void error(char* error_message,int line)
{
    char str[5];
    sprintf(str,"%d:",line);
    strcat(str,error_message);
    perror(str);
    exit(EXIT_FAILURE);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值