Linux设计本人编写more命令仓酷云
Linux的常用命令find,察看man文档,初学者一定会觉得太复杂而不原意用,但是你一旦学会就爱不释手。more命令能够完成的功效是很丰厚的,包含形式查找。明天我们只是完成它的一个基础功效:
[*]more文件列表
[*]在屏幕注释显现已读的百分比
[*]按下回车显现下一行
[*]按下空格显现下一屏
[*]按下q加入
[*]按回车、空格、q时没有回显
这里有几个成绩:
[*]要在屏幕注释显现已读的百分比,那我们必需先猎取文件列表中各个文件的长度,这个可使用体系挪用lstat
#include<sys/stat.h>
structstat*buf;
lstat("filename",buf)//猎取文件形态
filesize+=buf->st_size;//猎取文件巨细
[*]要显现整屏内容,我们就必要晓得一屏能够显现几行,然后从文件中读出这么多行显现在屏幕上。
#include<termios.h>
structwinsize*ws;
ws=(structwinsize*)malloc(sizeof(structwinsize));
memset(ws,0x00,sizeof(structwinsize));
ioctl(STDIN_FILENO,TIOCGWINSZ,ws);
intwidth=ws->ws_col;
intheight=ws->ws_row;
[*]禁用回显
#include<termios.h>
structtermiosts;//终端属性
tcgetattr(STDIN_FILENO,&ts);//猎取终端属性
ts.c_lflag&=(~ECHO);//制止回显
tcsetattr(STDIN_FILENO,TCSAFLUSH,&ts);//设置终真个新属性
[*]从终端读取单个字符后当即前往,不必要按回车
#include<termios.h>
structtermiosts;//终端属性
tcgetattr(STDIN_FILENO,&ts);//猎取终端属性
ts.c_lflag&=(~ICANON);//设置终端为非尺度形式
ts.c_cc=1;//这两行当必要从终端猎取字符时当即前往,不必要按回车键
ts.c_cc=0;
tcsetattr(STDIN_FILENO,TCSAFLUSH,&ts);//设置终真个新属性
完全代码:
#include<stdio.h>#include<sys/ioctl.h>#include<fcntl.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<string.h>#include<termios.h>voidgettermsize(int*w,int*h);//猎取终端尺寸voiddo_more(FILE*);//依据see_more猎取的用户输出,显现更多的文件内容或加入intsee_more();//捕捉用户的输出指令voidsettermattr();//设置终端属性intwidth;//终端屏幕宽度intheight;//终端屏幕高度intfilesize;//文件的巨细intreadsize;//已显现的内容长度structtermiosts,ots;//终端属性intmain(intargc,char*argv[]){gettermsize(&width,&height);settermattr();FILE*fp;structstat*buf;filesize=0;readsize=0;buf=(structstat*)malloc(sizeof(structstat));memset(buf,0x00,sizeof(structstat));if(argc==1)//假如没有指定文件,则从尺度输出读取内容do_more(stdin);else{//从文件列表中读取内容inti;for(i=1;i<argc;i++){//more命令前面大概跟多个文件if((fp=fopen(*(argv+i),"r"))!=0){//以只读情势翻开文件if(lstat((constchar*)*(argv+i),buf)==0){//猎取文件形态filesize+=buf->st_size;//猎取文件巨细printf("fs=%ld
",buf->st_size);}else{exit(1);}fclose(fp);//封闭文件}else{//翻开文件失利,加入程序exit(1);}}printf("size=%d
",filesize);for(i=1;i<argc;i++){//more命令前面大概跟多个文件if((fp=fopen(*(argv+i),"r"))!=0){//以只读情势翻开文件do_more(fp);//显现文件内容fclose(fp);//封闭文件}else{//翻开文件失利,加入程序exit(1);}}}tcsetattr(STDIN_FILENO,TCSANOW,&ots);return0;}voidgettermsize(int*w,int*h){structwinsize*ws;ws=(structwinsize*)malloc(sizeof(structwinsize));memset(ws,0x00,sizeof(structwinsize));ioctl(STDIN_FILENO,TIOCGWINSZ,ws);*w=ws->ws_col;*h=ws->ws_row;}voidsettermattr(){tcgetattr(STDIN_FILENO,&ts);//猎取终端属性ots=ts;//备份终端属性ts.c_lflag&=(~ECHO);//制止回显ts.c_lflag&=(~ICANON);//设置终端为非尺度形式ts.c_cc=1;//这两行当必要从终端猎取字符时当即前往,不必要按回车键ts.c_cc=0;tcsetattr(STDIN_FILENO,TCSAFLUSH,&ts);//设置终真个新属性。TCSAFLUSH暗示输入行列空了今后才失效,失效之前的输入行列被flush}voiddo_more(FILE*fp){intlinesize=width;charline;intnum_of_lines=0;//纪录本次读了几行intreply;//纪录see_more()的前往值FILE*fp_tty;while(fgets(line,linesize,fp)){//从文件中读取一行内容readsize+=strlen(line);//读出的内容长度if(num_of_lines==height){//假如满屏了reply=see_more();//从键盘猎取用户输出的命令if(reply==0){//用户不必要显现更多内容了,要加入tcsetattr(STDIN_FILENO,TCSANOW,&ots);exit(0);}num_of_lines-=reply;}if(fputs(line,stdout)==EOF){//把这行内容显现在用户屏幕上tcsetattr(STDIN_FILENO,TCSANOW,&ots);//TCSANOW暗示修正当即失效perror("fputs");exit(1);}num_of_lines++;}}intsee_more(){intc;printf("