Linux C编程实战——第六章 文件操作_项目实现_自写ls命令

自写ls命令


根据文件的操作,参考书籍资料,编写了ls命令   目前实现了 -R  -r   -l  -a   -i  -t 功能

直接上代码(已经加入了详细注释):

有不足请指教!      ——开心!



/*************************************************************************
	> File Name: my_ls.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年07月19日 星期二 09时35分44秒
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <linux/limits.h>
#include <dirent.h>
#include <grp.h>
#include <pwd.h>
#include <errno.h>

#define PARAM_NONE 0
#define PARAM_A    1
#define PARAM_L    2
#define PARAM_I    4
#define PARAM_R    8
#define PARAM_T    16
#define PARAM_RR   32
#define MAXROWLEN  80

int g_leave_len = MAXROWLEN;
int g_maxlen;

/******************错误分析********************/
void my_err(const char *err_string,int line)
{
	fprintf(stderr, "line:%d ", line);
	perror(err_string);
	exit(1);
}


/*********************************************
 * 功能 :输出文件信息  参数  -l
 * 参数1  文件信息
 * 参数2  文件名
 * 参数3  文件显示颜色
 *********************************************/
void display_attribute(struct stat buf,char * name,int filecolor)
{
    char colorname[NAME_MAX + 30];
	char buf_time[32];
	struct passwd *psd;
	struct group  *grp;
/****************文件类型**********************/
	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");
	}


/********************文件权限**************************/ 

    //拥有者权限
    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_IXGRP){
		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("\t");	
    //通过用户和组id得到用户的信息和其所在组的信息
	psd = getpwuid(buf.st_uid);
	grp = getgrgid(buf.st_gid);

	printf("%4d ",buf.st_nlink);    //打印文件的硬链接数
	printf("%-8s",psd->pw_name);    //打印用户的名字
	printf("%-8s", grp->gr_name);   //打印用户组的名字

	printf("%6d", buf.st_size);     //打印文件大小
	strcpy(buf_time,ctime(&buf.st_mtime));//把时间转换成普通表示格式

	buf_time[strlen(buf_time)-1]='\0';    //去掉换行符
	printf("  %s", buf_time);//输出时间 
    sprintf(colorname,"\033[%dm%s\033[0m",filecolor,name);
	printf(" %-s\n", colorname);
}





/*******************************
 * 功能 :输出文件名
 * 参数1 文件名
 * 参数2 文件显示参数
 * *****************************/

void display_single(char *name,int filecolor)
{
	char colorname[NAME_MAX + 30];
	int i,len;
    //剩余空间不够,就进行换行 
	if(g_leave_len < g_maxlen){
		printf("\n");
		g_leave_len=MAXROWLEN;
	}
    //名字的长度
	len = strlen(name);
	len = g_maxlen - len;

	sprintf(colorname,"\033[%dm%s\033[0m",filecolor,name);
	printf(" %-s", colorname);
	//输出若个个空格,补够一个单位
    for(i=0;i<len;i++)
		printf(" ");
	printf(" ");
    //更新剩余空间
	g_leave_len -= (g_maxlen+2);
}


/********************************************
 * 功能:输出带有i_node的文件信息
 * 参数1 文件信息
 * 参数2 文件名
 * 参数3 显示颜色
 * *****************************************/
void display_st_ino(struct stat buf,char *name,int filecolor)
{
	char colorname[NAME_MAX + 30];
	int i,len;
    //剩余空间不够,就进行换行 
	if(g_leave_len < g_maxlen+8){
		printf("\n");
		g_leave_len=MAXROWLEN;
	}

	printf("%d ", buf.st_ino);
    //名字的长度
	len = strlen(name);
	len = g_maxlen - len;

	sprintf(colorname,"\033[%dm%s\033[0m",filecolor,name);
	printf(" %-s", colorname);
	//输出若个个空格,补够一个单位
    for(i=0;i<len;i++)
		printf(" ");
	printf(" ");
    //更新剩余空间
	g_leave_len -= (g_maxlen+2+8);
}




/**********************************************
 * 功能:根据参数及路径输出单个文件信息
 * 参数1 参数信息
 * 参数2 单个文件路径
 * ********************************************/
void display(int flag,char * pathname)
{
    int filecolor=37;
	int    i,j;
	struct stat  buf;//文件信息buf
	char   name[NAME_MAX + 1];
	for(i=0,j=0; i<strlen(pathname);i++)
	{
		if(pathname[i] == '/')
		{
			j=0;
			continue;
		}
		name[j++]=pathname[i];
	}
	name[j]='\0';


	if(lstat(pathname,&buf) == -1){
		my_err("stat",__LINE__);
	}

	if(S_ISLNK(buf.st_mode)){

	} else if(S_ISREG(buf.st_mode)){

	} else if(S_ISDIR(buf.st_mode)){
        filecolor=34;
	} else if(S_ISCHR(buf.st_mode)){
        filecolor=33;
	} else if(S_ISBLK(buf.st_mode)){
        filecolor=33;
	} else if(S_ISFIFO(buf.st_mode)){

	} else if(S_ISSOCK(buf.st_mode)){

	}

    if(filecolor == 37&&
    		( (buf.st_mode & S_IXUSR)||
    		  (buf.st_mode & S_IXGRP)||
    		  (buf.st_mode & S_IXOTH)   )  ){
    	filecolor=32;
    }
    	



/********************文件权限**************************/ 

    
	switch(flag)
	{
		case PARAM_NONE:
			if(name[0]!='.'){
				display_single(name,filecolor);
			}
			break;

		case PARAM_I:
			if(name[0]!='.'){
				display_st_ino(buf,name,filecolor);
			}
			break;


		case PARAM_A:
			display_single(name,filecolor);
			break;

		case PARAM_L:
			if(name[0] != '.'){
				display_attribute(buf, name,filecolor);
			}
			break;

		case PARAM_A+PARAM_L:
			display_attribute(buf,name,filecolor);
			break;

		case PARAM_A+PARAM_I:
			display_st_ino(buf,name,filecolor);
			break;

		case PARAM_L+PARAM_I:
			if(name[0] != '.'){
				printf("%d ",buf.st_ino);
				display_attribute(buf, name,filecolor);
			}
			break;

		case PARAM_A+PARAM_L+PARAM_I:
			{
				printf("%d ",buf.st_ino);
				display_attribute(buf,name,filecolor);
			}
			break;
				
		default:
			break;
	}
}



/****************************************
* 功能:输出目录信息
* 参数1 参数信息
* 参数2 目录文件路径
* *************************************/
void display_dir(int flag_param,char *path)
{
	DIR   *dir;
	long   t;
	int flag_param_temp;
	struct stat buf;
	struct dirent  *ptr;
	int    count = 0;
	char   filename[256][PATH_MAX+1],temp[PATH_MAX+10];
	long   filetime[256][1];
	flag_param_temp=flag_param;
	dir = opendir(path);

	if(dir == NULL){
		my_err("opendir",__LINE__);
	}
	//解析文件个数,及文件名的最长值
    while((ptr = readdir(dir))!= NULL){
		if(g_maxlen < strlen(ptr->d_name))
			g_maxlen = strlen(ptr->d_name);
		count++;
	}
	
    closedir(dir);

	if(count>256)
        printf("%d :too many files under this dir",__LINE__);
	
    

    int i,j,len = strlen(path);
	dir = opendir(path);
    //得到该目录下的所有文件的路径	
    for(i=0;i < count; i++)
    {
		ptr = readdir(dir);
		if(ptr == NULL){
			my_err("opendir",__LINE__);
		}

		strncpy(filename[i],path,len);
		filename[i][len] = '\0';
		strcat(filename[i],ptr->d_name);
		filename[i][len+strlen(ptr->d_name)] = '\0';
    }

	closedir(dir);



    //插入排序

    if(flag_param & PARAM_T)//根据时间排序
    {
    	for(i=0;i<count;i++)
    	{
    		stat(filename[i],&buf);
    		filetime[i][0]=buf.st_mtime;
    	}

    	for(i=0;i<count;i++)
		{
			for(j=i;j<count;j++)
			{
				if(filetime[i][0]<filetime[j][0])
				{
					t 		      =filetime[i][0];
					filetime[i][0]=filetime[j][0];
					filetime[j][0]=t;
					strcpy(temp,filename[i]);
					strcpy(filename[i],filename[j]);
					strcpy(filename[j],temp);
				}
			}
		}
		flag_param -= PARAM_T;
    }
    else//根据名字排序
    {
    	for(i=0;i<count;i++)
		{
			for(j=i;j<count;j++)
			{
				if(strcmp(filename[i],filename[j])>0)
				{
					strcpy(temp,filename[i]);
					strcpy(filename[i],filename[j]);
					strcpy(filename[j],temp);
				}
			}
		}
    }
	

    //输出文件

    if(flag_param & PARAM_R)//逆序
    {
    	flag_param -= PARAM_R;
    	if(flag_param & PARAM_RR)//递归输出
		{
			flag_param -= PARAM_RR;
    		for (i = count-1; i >= 0; i--)
			{
				stat(filename[i],&buf);
				if(S_ISDIR(buf.st_mode))
				{

					len=strlen(filename[i]);
					if(filename[i][len-1]=='.' && filename[i][len-2]=='/'
						||filename[i][len-1] == '.' && filename[i][len-2]=='.'&&filename[i][len-3]=='/') 
						continue;
					
					printf("\n\n%s :\n",filename[i]);
					len=strlen(filename[i]);
					filename[i][len]='/';
					filename[i][len+1]='\0';		
					display_dir(flag_param_temp,filename[i]);
				}
				else
					display(flag_param,filename[i]);
			}
		}
		else
		{
			for (i = count-1; i >= 0; i--)
			{
				display(flag_param,filename[i]);
			}

		}
    }
    else
    {
    	if(flag_param & PARAM_RR)
		{
			flag_param -= PARAM_RR;
    		for (i = 0; i < count; i++)
			{
				stat(filename[i],&buf);
				if(S_ISDIR(buf.st_mode))
				{
					len=strlen(filename[i]);
					if(filename[i][len-1]=='.' && filename[i][len-2]=='/'
						||filename[i][len-1] == '.' && filename[i][len-2]=='.'&&filename[i][len-3]=='/') 
						continue;
					
					printf("\n\n%s :\n",filename[i]);
					len=strlen(filename[i]);
					filename[i][len]='/';
					filename[i][len+1]='\0';		
					display_dir(flag_param_temp,filename[i]);
				}
				else
					display(flag_param,filename[i]);
			}
		}
		else
		{
			for (i = 0; i < count; i++)
			{
				display(flag_param,filename[i]);
			}

		}
    }
	if((flag_param & PARAM_L) == 0) 
		printf("\n");
}






int main(int argc, char const *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++;
		}
	}
    
    
    //利用位运算确定具体参数
	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] == 'i'){
			flag_param |= PARAM_I;
			continue;
		} 
		else if(param[i] == 'r'){
			flag_param |= PARAM_R;
			continue;
		} 
		else if(param[i] == 't'){
			flag_param |= PARAM_T;
			continue;
		}else if(param[i] == 'R'){
			flag_param |= PARAM_RR;
			continue;
		}    
		else{
			printf("my_ls: incalid 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 0;
	}
    
	i =1;
	do{	
        if(argv[i][0] == '-')
        {
			i++;
			continue;
		} 
        else 
        {
            //得到具体路径
			strcpy(path, argv[i]);
			if(stat(path,&buf) == -1)
				my_err("stat",__LINE__);

	    	//判断是否为目录文件	
            if(S_ISDIR(buf.st_mode))
			{
                //如果目录最后忘记了/则加上
				if(path[strlen(argv[i]) - 1] != '/')
				{
					path[strlen(argv[i])]  = '/';
					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);
    return 0;
}









  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值