北京邮电大学Unix编程环境课程第一次实验报告ls命令.docx
《北京邮电大学Unix编程环境课程第一次实验报告ls命令.docx》由会员分享,可在线阅读,更多相关《北京邮电大学Unix编程环境课程第一次实验报告ls命令.docx(17页珍藏版)》请在冰豆网上搜索。
北京邮电大学Unix编程环境课程第一次实验报告ls命令
实验报告
实验名:
Unix编程第一次实验
课程名:
Unix编程环境
姓名:
学号:
班级:
实验目的:
练习vi,使用UNIX的系统调用和库函数,体会UNIX文件通配符的处理方式以及命令对选项的处理方式。
实验要求:
编程实现程序list.c,列表普通磁盘文件(不考虑目录和设备文件等),列出文件名和文件大小。
与ls命令类似,命令行参数可以有0到多个
Ø0个参数:
列出当前目录下所有文件
Ø参数为普通文件:
列出文件
Ø参数为目录:
列出目录下所有文件
实现自定义选项r,a,l,h,m以及--
Ør递归方式列出子目录
Øa列出文件名第一个字符为圆点的普通文件(默认情况下不列出文件名首字符为圆点的文件)
Øl后跟一整数,限定文件大小的最小值(字节)
Øh后跟一整数,限定文件大小的最大值(字节)
Øm后跟一整数n,限定文件的最近修改时间必须在n天内
Ø显式地终止命令选项
程序说明:
1)命令选项的存储:
structoptions
{
IntaFlag,
rFlag,lFlag,hFlag,mFlag;
longlPara,hPara;
intmPara;
};
采用structoptions结构存储命令的选项,flag代表有无此选项,例如aFlag为1就表示有“-a”选项,aFlag为0则表示没有“-a”选项。
lPara、hPara和mPara用来存储”-l”、”-h”、”-m”选项所带的参数。
2)命令的读取:
structpath
{
char*path;
structpath*next;
};
采用函数getCommend读取命令,声明一个opEnd变量用来指示选项的输入是否结束。
opEnd初始为0,代表选项的输入没有结束,当遇到“--“之后,opEnd置为1,代表选项输入结束。
在opEnd为0的时候,命令中以”-“开头的,都认为是一个选项,在opEnd为1的时候,命令中以”-“开头的则不作为选项而作为命令的参数。
在识别选项的同时,也要读入命令的参数,命令的参数也就是文件地址,存储在结构structpath所组成的链表当中。
在读完命令之后,需要判断一下链表是否为空,如果链表是空的则代表命令中没有参数,这是需要程序自动得把当前目录即”./“加入链表当中。
3)选项的判断:
intjudje(structoptionsoption,structstatinfo,char*fileName)
采用函数judje函数判断一个文件是否满足选项的要求,如果满足要求返回1,否则返回0。
4)选项的参数的获取:
intgetPara(char*option)
采用函数getPara获取选项所带的参数,如果参数合法则把参数转化为int并返回,如果参数不合法,比如参数中字母或符号等则返回-1;
5)打印:
voidlistFiles(char*path,structoptionsoption)
采用函数listFiles打印文件,当需要递归时,把当前打印的目录和需要递归的文件目录合并在一起传入listFiles中,进行递归。
实验结果:
1)输入命令:
./list不加选项和参数
2)输入命令:
./list–a打印文件名”.”开头的文件名及大小
3)输入命令:
./list–l4000输出大小在4000自己以上的文件名及大小
4)输入命令:
./list–h5000输出大小在5000字节一下的文件名及大小
5)输入命令:
./list–m2打印两天之内修改过的文件名及大小
6)输入命令:
./list–r|more循环打印文件名及大小
7)输入命令:
./list–r---a循环打印文件名是-a的文件夹
8)输入命令:
./listtest*(相当于./listtesttest2)
Test:
Test2:
9)输入命令:
./listlist.c打印list.c文件
10)输入命令:
./list–l3000–h5000–r–a--/home/andy|more(复杂命令)
实验总结:
在打印过程中需要考虑一下集中特殊情况:
1)命令中没有参数
2)输入的路径本身就是一个文件
3)目录中“.”文件和”..”文件的问题。
对于第一种情况:
假如没有考虑到这个情况会导致没有任何输出的问题,而这个情况下是应该打印当前目录的。
在编程中可以判断一下命令是否带有参数,如果没有参数就把当前目录当作参数传给程序。
对于第二种情况:
假如不考虑这个问题,会导致直接显示无法打开文件的情况。
编程中可以首先判断一下,输入的参数是否是一个文件来解决。
如果是一个文件就直接打印它的文件名和大小。
对于第三种情况:
假如不考虑这个问题,会导致无限递归的产生。
因为”.“文件开打后回到上层目录,打开这个目录发现里面还是有一个”.“文件,在编写”-r“选项是导致无限递归。
编程时应该额外处理”.“文件和”..”文件,在递归之前应该判断需要递归的目录是否是一个”.“文件或”..”文件,如果是,则不应该递归,如果不是,则可以递归。
实验代码:
#include
#include
#include
#include
#include
#include
#include
structpath
{
char*path;
structpath*next;
};
structoptions
{
intaFlag,rFlag,lFlag,hFlag,mFlag;
longlPara,hPara;
intmPara;
};
intjudje(structoptionsoption,structstatinfo,char*fileName)
{
longcurrentTime=(long)time(NULL);
if(option.aFlag==0&&fileName[0]=='.')
return0;
if(option.lFlag==1&&(long)info.st_sizereturn0;
if(option.hFlag==1&&(long)info.st_size>option.hPara)
return0;
if(option.mFlag==1&&(currentTime-(long)info.st_mtime)/86400>=option.mPara)
return0;
return1;
}
/*
*usetheoptiontodeterminewhetherafileshouldbeprinted
*/
voidlistFiles(char*path,structoptionsoption)
{
DIR*dir;
structdirent*files;
//structfile*file;
intflag;//canbeprint?
structstatinfoTmp;
if(stat(path,&infoTmp)!
=-1&&!
S_ISDIR(infoTmp.st_mode)){
printf("%-50s%ld\n",path,(long)infoTmp.st_size);
return;
}
elseif(stat(path,&infoTmp)==-1){
fprintf(stderr,"cannotreadthestatusof%s\n",path);
return;
}
if((dir=opendir(path))==NULL){
fprintf(stderr,"cannotopen%s\n",path);
}
else{
while((files=readdir(dir))!
=NULL){
flag=1;
structstatinfo;
chartmp[200];
strcpy(tmp,path);
strcat(tmp,"/");
strcat(tmp,files->d_name);
if(stat(tmp,&info)==-1)
fprintf(stderr,"cannotreadthestatusof%s\n",files->d_name);
else{
flag=judje(option,info,files->d_name);
if(flag==1){
printf("%-50s%ld\n",files->d_name,(long)info.st_size);
}
if(option.rFlag==1&&S_ISDIR(info.st_mode)&&flag==1){//ifit'sadirand-rexists
if(strcmp(files->d_name,".")!
=0&&strcmp(files->d_name,"..")!
=0)
listFiles(tmp,option);
}
}
}
closedir(dir);
}
}
/*
*gettheparameterafteranoption
*/
intgetPara(char*option)
{
inti=0;
inttmp=0;
for(;option[i]!
='\0';i++){
if(option[i]>='0'&&option[i]<='9')
tmp=tmp*10+option[i]-'0';
else
return-1;
}
returntmp;
}
intgetCommend(intargc,char**args)
{
inti;//-r-a-l-h-m--
intopEnd=0;
char*tmp;
structoptionsop;
structpath*pathHead=NULL,*currentPtr;
op.lFlag=0;
op.hFlag=0;
op.aFlag=0;
op.mFlag=0;
op.rFlag=0;
/*
*dealwiththecommensfindtheoptionsandfilepathes
*/
for(i=1;i<=argc-1;i++){
if(args[i][0]=='-'&&opEnd==0){//it'sanoption
if(args[i][2]!
='\0'){
fprintf(stderr,"ls:
invalidoption\n");//thisoptioniswrong
return0;
}
switch(args[i][1]){
case'a':
op.aFlag=1;
break;
case'r':
op.rFlag=1;
break;
case'l':
op.lFlag=1;
op.lPara=getPara(args[++i]);
if(op.lPara==-1){
fprintf(stderr,"ls:
invalidoption\n");//wronginput
return0;
}
break;
case'h':
op.hFlag=1;
op.hPara=getPara(args[++i]);
if(op.hPara==-1){
fprintf(stderr,"ls:
invalidoption\n");
return0;
}
break;
case'm':
op.mFlag=1;
op.mPara=getPara(args[++i]);
if(op.mPara==-1){
fprintf(stderr,"ls:
invalidoption\n");
return0;
}
break;
case'-':
opEnd=1;
break;
}
}
else{
structpath*newPtr=(structpath*)malloc(sizeof(structpath));
newPtr->path=args[i];
newPtr->next=NULL;
if(pathHead==NULL)
pathHead=newPtr;
else
currentPtr->next=newPtr;
currentPtr=newPtr;
}
}
/*
*dealwitheverypathinthecommend
*/
if(pathHead)
while(pathHead!
=NULL){
printf("%s:
\n",pathHead->path);
listFiles(pathHead->path,op);
pathHead=pathHead->next;
}
else{
pathHead=(structpath*)malloc(sizeof(structpath));
pathHead->path="./";
pathHead->next=NULL;
listFiles(pathHead->path,op);
}
return1;
}
voidmain(intargc,char**args)
{
getCommend(argc,args);
return;
}