首页 > 其他分享 >改进ls

改进ls

时间:2022-10-16 15:45:21浏览次数:52  
标签:head name int length st 改进 ls pnext

功能要求

运行结果

源代码

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <memory.h>
#include <malloc.h>
#include <getopt.h>
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <error.h>
#include <sys/types.h>
#include <linux/kdev_t.h>


#define  OPT_v        0x0001   /* -v 选项:查看本软件版本 */
#define  OPT_h        0x0002   /* -h 选项:查看本软件帮助 */
#define  OPT_l        0x0004   /* -l 选项:长型(long)显示 */
#define  OPT_a        0x0008   /* -a 选项:显示所有文件(all)*/
#define  OPT_R        0x0010   /* -R 选项:显示子目录内容 */
#define  OPT_f        0x0020   /* -f 选项:不排序 */


#define DONE_SUCCESS  0


typedef struct _Node
{
	char path[1024];
	char name[256];
	int length;
	struct stat st;
	struct _Node *pnext;
} nNode;

//由nCol构成的链表用于存储每列字符串在终端的宽度
typedef struct _Col {
	int length;//某列字符串在终端的宽度
	struct _Col *pnext;
} nCol;


int createlslink(char *path,int flag,nNode **head)
{
	DIR * dp;
	struct dirent *entry;
	struct stat statbuf;
	nNode *p;
	char  abspath[1024];
	if((dp=opendir(path))==NULL)
	{
		fprintf(stderr,"cannot open directory:%s\n",path);
		return -1;
	}
	
	if(chdir(path) == -1)
	{
		fprintf(stderr,"cannot cd directory:%s\n",path);
		return -2;
	}

	if(NULL==getcwd(abspath,1024))
	{
		fprintf(stderr,"getcwd error!\n");
		return -3;
	}
	
	while((entry=readdir(dp)) != NULL)
	{
		lstat(entry->d_name,&statbuf);
		if((!(flag & OPT_a)) && (entry->d_name[0]=='.'))   /*没有选项 -a 则不显示.开头的文件(或目录)名*/
			continue;
		else
		{
			p = (nNode *)malloc(sizeof(nNode));
			p->pnext = *head;
			*head = p;
			(*head)->length = strlen(entry->d_name);
			strcpy((*head)->path,abspath);
			strcpy((*head)->name,entry->d_name);
			memcpy(&((*head)->st),&statbuf,sizeof(struct stat));
		}
	}

	if(-1==chdir(".."))
	{
		fprintf(stderr,"cannot cd directory:..\n");
		return -3;
	}

	if((closedir(dp)) ==-1)
	{
		fprintf(stderr,"cannot close dp\n");
		return -4;
	}

	return DONE_SUCCESS;
}


void sortlslink(nNode *head,int flag)
{
	nNode *p,*q,r;
	int  msuccess;
	if(!head)
		return;

	if(flag & OPT_f)
	{
		;
	}
	else
	{
		p = head;
		while(p->pnext) p = p->pnext;

		while(p!=head)
		{
			q=head;
			msuccess = 1;
			while(q->pnext)
			{
				if(strcasecmp(q->name,q->pnext->name)>0)
				{
					memcpy(&r,q,sizeof(nNode));
					strcpy(q->name,q->pnext->name);
					strcpy(q->path,q->pnext->path);
					q->length = q->pnext->length;
					memcpy(&q->st,&(q->pnext->st),sizeof(q->st));

					strcpy(q->pnext->name,r.name);
					strcpy(q->pnext->path,r.path);
					q->pnext->length = r.length;
					memcpy(&(q->pnext->st),&(r.st),sizeof(r.st));
					msuccess = 0;
				}

				if(q->pnext==p)
					break;
				q = q->pnext;
			}

			if(msuccess)
				break;
			p = q;
		}
	}
}


void format_long_print(nNode *head,int flag)
{
	nNode * p = head;
	char buf[12];
	struct passwd *password;
	struct group  *grp;
	struct tm * tm_ptr;

	char  linkfilebuf[1024];
	char pathfilename[1024];
	char filename[256];
	if(!p)
		return;

	while(p)
	{
		if( !strcmp(p->name,".") || !strcmp(p->name,".."))
		{
			printf("%s\n",p->name);
		}
		else
		{
			/*permission*/
			strcpy(pathfilename,p->path);
			strcpy(filename,p->name);

			memset(buf,'-',11);
			buf[11]=0;

			if(S_ISDIR(p->st.st_mode))       buf[0] = 'd';
			else if(S_ISCHR(p->st.st_mode))  buf[0] = 'c';
			else if(S_ISBLK(p->st.st_mode))  buf[0] = 'b';
			else if(S_ISFIFO(p->st.st_mode)) buf[0] = 'p';
			else if(S_ISLNK(p->st.st_mode))  buf[0] = 'l';
			else if(S_ISSOCK(p->st.st_mode)) buf[0] = 's';

			if(S_IRUSR&p->st.st_mode) buf[1] = 'r';
			if(S_IWUSR&p->st.st_mode) buf[2] = 'w';
			if(S_IXUSR&p->st.st_mode) buf[3] = 'x';

			if(S_IRGRP&p->st.st_mode) buf[4] = 'r';
			if(S_IWGRP&p->st.st_mode) buf[5] = 'w';
			if(S_IXGRP&p->st.st_mode) buf[6] = 'x';

			if(S_IROTH&p->st.st_mode) buf[7] = 'r';
			if(S_IWOTH&p->st.st_mode) buf[8] = 'w';
			if(S_IXOTH&p->st.st_mode) buf[9] = 'x';

			printf("%s ",buf);

			/*link number*/
			printf("%4ld ",p->st.st_nlink);

			/*owner*/
			password = getpwuid(p->st.st_uid);
			if(password)
			{
				printf("%s ",password->pw_name);
			}
			else
			{
				printf("%d ",p->st.st_uid);
			}

			/* group */
			grp= getgrgid(p->st.st_gid);
			if(grp)
			{
				printf("%s ",grp->gr_name);
			}
			else
			{
				printf("%d ",p->st.st_gid);
			}

			/*file bytes or dev number*/
			if(S_ISBLK(p->st.st_mode) || S_ISCHR(p->st.st_mode))
			{
				printf("%3lu,",MAJOR(p->st.st_rdev));
				printf("%3lu ",MINOR(p->st.st_rdev));
			}
			else
			{
				printf("%7lu ",p->st.st_size);
			}

			/*time*/
			tm_ptr = localtime(&(p->st.st_mtime));
			printf("%02d-%02d ",tm_ptr->tm_mon+1,tm_ptr->tm_mday);
			printf("%02d:%02d ",tm_ptr->tm_hour,tm_ptr->tm_min);

			/*filename */
			if(S_ISDIR(p->st.st_mode))
				printf("\033[;34m%s\033[0m\n",filename);
			else
				printf("%s ",filename);

			if(S_ISLNK(p->st.st_mode))
			{
				strcat(pathfilename,"/");
				strcat(pathfilename,p->name);
				int rslt=readlink(pathfilename,linkfilebuf,1024);
				if (rslt<0)
				{
					printf("readlink error!\n");
					exit(-1);
				}

				linkfilebuf[rslt]='\0';
				printf("-> \033[;32m%s\033[0m",linkfilebuf);
			}
			printf("\n");
		}
		p = p->pnext;
	}
	return;
}


//返回nCol链表包含每列字符串在终端的宽度,rows行数
nCol* getColsList(nNode *head, int rows)
{
	int cols = 0;

	nCol *colsList = (nCol*)malloc(sizeof(nCol));
	nCol *pList = colsList;
	nNode * p = head;
	int i = 0;
	int maxCol = 0;

	while(p) {
		if(p->length > maxCol)
			maxCol = p->length;
		i++;
		//在一列内找到最长的字符串
		if(i == rows) {
			cols++;
			pList->pnext = (nCol*)malloc(sizeof(nCol));
			pList = pList->pnext;
			pList->length = maxCol + 2;//字符串在终端的宽度
			maxCol = 0;
			i = 0;
		}
		p = p->pnext;
	}
	if(maxCol != 0) {
		cols++;
		pList->pnext = (nCol*)malloc(sizeof(nCol));
		pList = pList->pnext;
		pList->length = maxCol + 2;
		maxCol = 0;
		i = 0;
	}
	pList->length -= 2;
	colsList->length = cols;

	return colsList;
}

//返回行数
int getRows(nNode *head)
{
	//获得终端宽度
	struct winsize size;
	ioctl(STDIN_FILENO,TIOCGWINSZ,&size);

	int rows = 0;//行数
	int printCol = size.ws_col + 1;//一行最大宽度
	int maxCol = 0;
	int nodeCount = 1;

	//行数增加,计算某行数对应宽度,小于行最大宽度则满足要求
	while(printCol > size.ws_col && rows < nodeCount) {
		rows++;
		printCol = 0;
		nNode * p = head;
		int i = 0;
		while(p) {
			if(p->length > maxCol)
				maxCol = p->length;
			i++;
			if(i == rows) {
				printCol += maxCol + 2;
				maxCol = 0;
				i = 0;
			}
			p = p->pnext;
			if(rows == 1) {
				nodeCount++;
			}
		}
		if(rows == 1) {
			nodeCount--;
		}
		printCol += maxCol + 1;
		if(nodeCount != 0 && nodeCount / rows * rows == nodeCount) {
			printCol -= 2;
		}
		maxCol = 0;
	}

	return rows;
}

//排版
void pageMaker(nNode *head)
{
	//计算行数
	int rows = getRows(head);
	//计算每列宽度
	nCol *colsList = getColsList(head, rows);

	//列宽度转换为数组
	int *colsArray = (int*)malloc(sizeof(int) * colsList->length);
	nCol *pCols = colsList->pnext;
	int i;
	for(i = 0; i < colsList->length; i++) {
		colsArray[i] = pCols->length;
		pCols = pCols->pnext;
	}

	//按行数分组,即最终一列一列输出
	nNode **pColIndex = (nNode**)malloc(sizeof(nNode*) * colsList->length);
	nNode *pNode = head;
	int j;
	nNode *preNode;
	for(i = 0; i < colsList->length; i++) {
		pColIndex[i] = pNode;
		for(j = 0; j < rows && pNode != NULL; j++) {
			if(j == rows - 1) {
				preNode = pNode;
			}
			pNode = pNode -> pnext;
			if(j == rows - 1) {
				preNode -> pnext = NULL;
			}
		}
	}

	//按输出顺序链接节点,文件名之间加入空格
	nNode *Head = (nNode*)malloc(sizeof(nNode));
	nNode *pHead = Head;
	int endCol = colsList->length - 1;
	while(colsList->length != 0 && pColIndex[0] != NULL) {
		for(i = 0; i < colsList->length; i++) {
			if(pColIndex[i] != NULL) {
				int addLength = colsArray[i] - pColIndex[i] -> length;
				int j;
				for(j = 0; j < addLength; j++) {
					(pColIndex[i] -> name)[pColIndex[i] -> length] = ' ';
					(pColIndex[i] -> name)[(pColIndex[i] -> length) + 1] = '\0';
					(pColIndex[i] -> length)++;
				}
				if(i == endCol) {
					(pColIndex[i] -> name)[pColIndex[i] -> length] = '\n';
					(pColIndex[i] -> name)[(pColIndex[i] -> length) + 1] = '\0';
					(pColIndex[i] -> length)++;
				}

				pHead -> pnext = pColIndex[i];
				pColIndex[i] = pColIndex[i] -> pnext;
				pHead = pHead -> pnext;
			} else if(endCol == colsList->length - 1) {
				endCol = colsList->length - 2;
				(pHead -> name)[pHead -> length] = '\n';
				(pHead -> name)[(pHead -> length) + 1] = '\0';
				(pHead -> length)++;
			}
		}
	}

	head = Head -> pnext;
}


void format_normal_print(nNode *head,int flag)
{
	//排版
	pageMaker(head);

	nNode * p = head;

	while(p)
	{
		if(  ( (strcmp(p->name,".")==0) || (strcmp(p->name,"..")==0) ) && (flag & OPT_a))
		{
			printf("%s",p->name);
		}
		else
		{
			if(S_ISDIR(p->st.st_mode))
				printf("\033[;32m%s\033[0m",p->name);
			else
				printf("%s",p->name);
		}
		p = p->pnext;
	}

	return;
}


void showlslink(nNode *head,int flag)
{
	if(flag & OPT_l)
		format_long_print(head,flag);
	else
		format_normal_print(head,flag);
	return;
}


void lspath(char *path,int flag)
{
	char pathname[1024];
	char filename[256];

	nNode *p = NULL;
	nNode *head = NULL;

	/*创建列文件链表 head*/
	if ((createlslink(path,flag,&head)) != DONE_SUCCESS)
	{
		printf("createlslink error!\n");
		return;
	}

	/* 对链表排序 */
	sortlslink(head,flag);

	/* 按选项显示链表内容  */
	showlslink(head,flag);

	/*如果节点不是子目录,则删除节点,否则当有-R选项时,列子目录内容后删除节点  */
	while(head)
	{
		p = head;
		head = head->pnext;

		if(S_ISDIR(p->st.st_mode) && (flag & OPT_R))
		{
			if( strcmp(p->name,".") && strcmp(p->name,"..") )
			{
				strcpy(pathname,p->path);
				strcat(pathname,"/");
				strcat(pathname,p->name);
				printf("\033[;32m%s:\033[0m\n",pathname);
				lspath(pathname,flag);
			}
		}

		free(p);
	}

	return;
}


//输入参数的排序算法
int cmp (const void *arg1 , const void *arg2)
{
	return -strcmp((*(char **)arg1), (*(char **)arg2));
}


int main(int argc,char *argv[])
{
	int opt;
	char path[1024];
	int listflag = 0;
	struct stat statbuf;
	nNode *phead = NULL;//保存输入的文件名
	nNode *pdhead = NULL;//保存输入的文件夹名

	struct option longopts[] = { {"help",0,NULL,'h'},{"version",0,NULL,'v'},{0,0,0,0}};

	while((opt=getopt_long(argc,argv,"afhlvR",longopts,NULL)) != -1)
	{
		switch(opt)
		{
		case 'a':
			listflag |= OPT_a;
			break;

		case 'f':
			listflag |= OPT_f;
			break;

		case 'h':
			listflag |= OPT_h;
			break;

		case 'l':
			listflag |= OPT_l;
			break;

		case 'v':
			listflag |= OPT_v;
			break;

		case 'R':
			listflag |= OPT_R;
			break;

		case '?':
			printf("Usage:\n %s -h \n or \n  %s --help \nfor help\n",argv[0],argv[0]);
			exit(-1);
		}
	}

	if(listflag & OPT_h )
	{
		printf("Usage:  %s -afhlvR [directory1 [directory2],...]\n",argv[0]);
		return 0;
	}
	else if(listflag & OPT_v)
	{
		printf("myls version 0.1\nCopyright by YCG 2015\n");
		return 0;
	}

	if(optind==argc)
	{
		/* 列当前目录文件 */
		if(NULL==getcwd(path,1024))
			return -1;

		lspath(path,listflag);
	}
	else
	{
		//对输入参数排序
		qsort(argv+optind, argc-optind, sizeof(char*), cmp);

		for(; optind<argc; optind++)
		{
			if(lstat(argv[optind],&statbuf)<0)
			{
				fprintf(stderr,"stat error\n");
				return -1;
			}
			if(S_ISDIR(statbuf.st_mode))
			{
				//文件夹加入pdhead指向的链表
				nNode *p = (nNode*)malloc(sizeof(nNode));
				p->length = strlen(argv[optind]);
				strcpy(p->name,argv[optind]);
				p->pnext = pdhead;
				pdhead = p;
			}
			else
			{
				//文件加入phead指向的链表
				nNode *p = (nNode*)malloc(sizeof(nNode));
				p->length = strlen(argv[optind]);
				strcpy(p->name,argv[optind]);
				memcpy(&(p->st),&statbuf,sizeof(struct stat));
				p->pnext = phead;
				phead = p;
			}
		}
		
		//输出文件
		if(phead!=NULL)
		{
			sortlslink(phead,listflag);
			showlslink(phead,listflag);
			if(argc>2 && pdhead!=NULL)
				printf("\n");
		}
		//输出文件夹
		while(pdhead!=NULL)
		{
			if(argc>2)
				printf("%s:\n", pdhead->name);
			lspath(pdhead->name,listflag);
			pdhead = pdhead->pnext;
			if(argc>2 && pdhead!=NULL)
				printf("\n");
		}
	}
	return 0;
}

标签:head,name,int,length,st,改进,ls,pnext
From: https://www.cnblogs.com/cqszxy2020/p/16796297.html

相关文章

  • 实现ls与改进
    目录实现lsls伪代码:查询ls功能:代码实现:码云链接:运行结果:对比ls:改进ls的实现:ls的改进中的问题:改进代码:码云链接:运行结果:改进对比:实现lsls伪代码:打开目录文件针对目录文......
  • [转]VUE devTools 安装方法
    为了安装Google浏览器的VUE调试工具,我们可以在 https://devtools.vuejs.org/guide/installation.html里点击安装或者可以从github.com下载源码后手动编译并添加到......
  • sqlserver分组后取一条默认数据
    select*fromTestUsera;id name phone1张三134272191582 张三 138278264953 李四 158495431554 王五 15884562583 按姓名分组后绑定个默认手机号selectb.n......
  • 改进ls的实现
    根据图示,改进lsls:显示文件目录列表-a:显示所有的文件,包括隐藏文件-l:列出长数据串,显示出文件的属性与权限等数据信息(常用)-i:结合-l参数列出每个文件的inode-d:仅列......
  • 实现ls
    学习目标参考伪代码实现ls的功能,提交代码的编译,运行结果截图,码云代码链接。打开目录文件针对目录文件读取目录条目显示文件名关闭文件目录文件代码#include<std......
  • SQL1001N is not a valid database name. SQLSTATE=2E000
    $db2createdbhcba_appstoreusingcodesetUTF-8territoryCNCOLLATEUSINGSYSTEM出现错误SQL1001N"hcba_appstore"isnotavaliddatabasename.SQLSTATE=2E0......
  • 改进ls的实现
    一、代码#include<stdio.h>#include<sys/types.h>#include<dirent.h>#include<sys/stat.h>#include<pwd.h>#include<grp.h>#include<unistd.h>......
  • Entity Framework教程-模型(Models)
    更新记录转载请注明出处:2022年10月16日发布。2022年10月10日从笔记迁移到博客。模型基础实体对象模型说明(EntityDataModel)EF使用实体对象模型进行增删改查(CRU......
  • E: Release file for http://mirrors.tuna.tsinghua.edu.cn/debian-security/dists/bu
    虚拟机yunupdate时间失效问题E:Releasefileforhttp://mirrors.tuna.tsinghua.edu.cn/debian-security/dists/bullseye-security/InReleaseisnotvalidyet(invalid......
  • drools_02_installation
    Drools7的产品组合DroolsEngine:包含DroolsExpert(规则引擎)和DroolsFusion(complexeventprocessing-CEP)DroolsandjBPMintegration:Drools/jBPMN和Sp......