北邮选修课unix期中实验报告
发布时间:2011-08-26 14:54:57
发布时间:2011-08-26 14:54:57
班级:08211312
学号:08211488
姓名:吴迪
班内序号:15
练习vi,使用UNIX的系统调用和库函数,体会UNIX文件通配符的处理方式以及命令对选项的处理方式。
编程实现程序list.c,列表普通磁盘文件(不考虑目录和设备文件等),列出文件名和文件大小。
与ls命令类似,命令行参数可以有0到多个
0个参数:列出当前目录下所有文件
参数为普通文件:列出文件
参数为目录:列出目录下所有文件
实现自定义选项r,a,l,h,m以及--
r 递归方式列出子目录
a 列出文件名第一个字符为圆点的普通文件(默认情况下不列出文件名首字符为圆点的文件)
l 后跟一整数,限定文件大小的最小值(字节)
h 后跟一整数,限定文件大小的最大值(字节)
m 后跟一整数n,限定文件的最近修改时间必须在n天内
-- 显式地终止命令选项分析
为了执行程序的方便,使用sudo指令将可执行文件list拷贝到/usr/bin/m_list
运行m_list即相当于运行./list
本程序实现了预定基本功能外,为方便调试,外加了-s选项:将文件夹属性也一起显示
多文件/文件夹(比如*命令)的访问使用链表struct Node动态存储对应路径位置。
另外,本程序能发现但未解决一部分新的问题,比如没有对命令-l-h-m参数不设置进行处理,而是直接报错;比如文件名如果为”-s”等命令形式,并未将其识别为文件名,而是判定为命令,除非前面加--(消除所有对命令的解析而是判断为文件/文件名路径参数),这一点和ls的功能保持了一致:解析*遇到上述情况也是采取- -方式而非智能识别。
另外对于初始不完整的文件路径(除非在默认目录下),没有遍历去搜索该路径,而是判断为错误/不完整路径不予识别
/**
*list function for unix/linux
*author: wd
*stu_id:08211488
*class_id:08211312
*final time 2011-4-28
*/
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
//debug message can use this print for printf or //printf
#define print //printf
//define the tab format
#define TABSPACES 9
//define print message
#define print_support_message printf("wait for higher(extern) versions to support this function!\n") //not required function
#define bool int //function para judgement -a -r (-s) -l -h -m
typedef struct Node
{
int pos;
struct Node *next;
}node;
bool is_a=0;
bool is_r=0;
bool is_l=0;
bool is_h=0;
bool is_m=0;
bool is_s=0; //s for show folders in r mode(default:not show)
int low=0; //low limit
int high=0; //up limit
int day=0; //day limit for last modify
void list(char *path);
void list_folder(char*folder_name);
int count_length(char*source)
{
char * it=source;int count = 0;
while(*it++!='\0')count++;
it--;
return count;
}
int main(int argc,char *argv[])
{
int i;int path_para;
int count_command_para=0;
int count_filename=0;
int stop=0;
node *head=(node*)malloc(sizeof(node)); //para list for filenames
node *current=head;
for(i=1;i
{
//printf("%s\n",argv[i]);
if(*(argv[i])=='-'&&!stop){
int breakp=0;
if(*(argv[i]+1)=='-'){stop=1; breakp=1;}
int j=2;char ch=*(argv[i]+1);
while(ch!='\0'&&!breakp){
count_command_para++;
switch(ch)
{
case 'a':is_a=1;break;
case 'r':is_r=1;break;
case 'l':{is_l=1;
//int low=(int)*argv[i+1];
low=atoi(argv[i+1]); i++;breakp=1;
//printf("arg=%d\n",low);
break;}
case 'h':is_h=1;
high=atoi(argv[i+1]); i++;breakp=1;
break;
case 'm':is_m=1;
day=atoi(argv[i+1]); i++;breakp=1;
break;
case 's':is_s=1; //show folders
break;
default:printf("other options!");print_support_message;break;
}
ch=*(argv[i]+(j++));
}
}
else {
count_filename++;path_para=i;
if(count_filename==1){
head->pos=i;
head->next=NULL;
}
else{
node *temp;
temp=(node*)malloc(sizeof(node));
temp->pos=i;
temp->next=NULL;
current->next=temp;
current=current->next;
}
printf("%s\n",argv[i]);
// printf("path_para==%d\n",path_para);
/*if(count_filename>1)
{
printf("Too many filenames or foldernames!");
print_support_message;
return 0;
}*/
}
}
char *path;
if(count_filename==0) {
char buf[80];
getcwd(buf,sizeof(buf));
//printf("%s\n",buf);
path = buf;
list(path);
free(head);
}
else{
current=head;
while(current!=NULL){
head=current;
path_para=current->pos;
path = argv[path_para]; //main file or folder path
//printf("%s\n",path);
list(path);
current=current->next;
free(head);
}
}
return 0;
}
void list_folder(char*folder_name)
{
DIR * dir;
struct dirent* ptr;
char *source;//folder_name;
source = (char*)malloc(sizeof(count_length(folder_name)));
memcpy(source,folder_name,count_length(folder_name));
source[count_length(folder_name)]='\0';
dir = opendir(folder_name);
if(chdir(source)==0){
//printf("change success!\n");
}
else{
//perror("change failed!\n");
}
if(dir==NULL){
printf("No such folder found!\n");
}
else{
while((ptr = readdir(dir))!=NULL)
{
//struct dirent* temp_ptr;
//first char of ptr->d_name is an integer 46
//which means '.'
char*path=ptr->d_name;
struct stat st;
int ret=stat(path,&st);
off_t size=st.st_size;
time_t timer=time(NULL);
//struct tm *time=localtime(&timer);
time_t betime=timer-st.st_mtime;
time_t time_limit;
time_limit=day*3600*24;
if(ret==-1)
{
printf("path error!\n");
}else{}
if(is_r){
if(ptr->d_type==4&&*(ptr->d_name)!=46){//not include file or dot from results
if(is_s==1){
if(is_l==1&&(int)size
else if(is_h==1&&(int)size>high) ;
else if(is_m==1&&(int)time_limit
else {
printf("name: %s type: %s location at %s\n",ptr->d_name,ptr->d_type==8?"file":"folder",source);
}
}
char* sub_folder_name=ptr->d_name;
list_folder(sub_folder_name);
}
}
if(ptr->d_type==8){
if((*(ptr->d_name)!=46)||(is_a&&*(ptr->d_name)==46))//second part is dot file
{
if(is_l==1&&(int)size
else if(is_h==1&&(int)size>high) ;
else if(is_m==1&&(int)time_limit
else {
printf("name: %s type: %s length %d location at %s\n",ptr->d_name,ptr->d_type==8?"file":"folder",(int)size,source);
//printf("last modified time: %d\n",(int)betime);
}
}
}
}
char old_path[80];
char new_path[80];
getcwd(old_path,sizeof(old_path));
char*begin=old_path;
char*end=strrchr(old_path,'/');
int len=end-begin;
memcpy(new_path,old_path,len);
new_path[len]='\0';
// printf("len=%d",len);
// printf("new =%s\n old =%s\n",new_path,old_path);
if(chdir(new_path)==0){
// printf("back success!\n");
}
else{
// perror("back failed!\n");
}
getcwd(old_path,sizeof(old_path));
// printf("current=%s\n",old_path);
closedir(dir);}
}
void list(char *path)
{
struct stat st;
int ret=stat(path,&st);
if(ret==-1)
{
printf("Such a path not found!\n");
}
else{
if(S_ISDIR(st.st_mode)){
list_folder(path);
}
else{
off_t size=st.st_size;
printf("name: %s type: file length %d \n",path,(int)size);//show file info
}
}
}
1 –a –r –m 1 Music
2 –a –r –m 3 Music
3 Music
4 –l 100 –h 5000 –m 1 /bin /etc
5 –ar –l 1000 –m 2
6 -- -as
7 -- -r
8 -- *
9 -- -a –s -r
10 *.c –l 100 –h 10000
本次实验练习使用了vi编辑器编写代码,熟悉了命令模式和编辑模式的转换过程和编辑特性。list函数功能实现过程中遇到过许多问题,通过对这些问题的研究和解决的过程温故了unix下c语言程序的编写。程序在不断修改过程中初步完成了所有题设对应功能。尽管又发现了新的问题而且最终没有编写对应的解决代码,但是能够提出这些问题和对应的解决方案。本次实验的个人基本目标已经达到。