#include"filecopy.c" #include<dirent.h> #define SIZE 100 /*递归输出文件和目录的名字*/
int distance=0; char src[SIZE],obj[SIZE],NAME[SIZE]; char *ptr=NAME; static bool entry(char*path); static bool walk(char*,bool(*fcn)(char*)); static bool push(char*); static bool pop(char*); static char *change(char*);
int main(int argc,char*argv[]) { NAME[0]='\0'; if(argv[1][0]=='.') push(getcwd(NULL,0));
strcpy(src,NAME); strcpy(obj,argv[2]); /*确定源文件的根目录和目标文件的根目录*/ ec_false(entry(argv[1])) /*从源文件的根目录开始工作*/ return 0; FIX(return 1;) }
static bool walk(char*path,bool(*func)(char*)) /*遍历一个目录,对其每个项目使用func函数*/ { DIR *sp=NULL; struct dirent *bp; int fd=-1; struct stat st;
ec_null(sp=opendir(path)) ec_neg1(fd=open(".",O_RDONLY))/*当前目录为待遍历的目录,先记录,再跳转*/ ec_neg1(chdir(path))
while(errno=0,(bp=readdir(sp))!=NULL){ if(strcmp(bp->d_name,".")==0||strcmp(bp->d_name,"..")==0) continue; else{ ec_false((*func)(bp->d_name)) } }
fchdir(fd); closedir(sp); return true;
EC_CLEANUP_BGN fchdir(fd); closedir(sp); return false; EC_CLEANUP_END }
static bool entry(char*path) { struct stat st; ec_neg1(lstat(path,&st)) int j; if((st.st_mode&S_IFMT)==S_IFDIR){ distance++; for(j=1;j<distance;j++) printf("\t"); if(path[0]!='.')push(path); printf("%s to %s\n",NAME,change(NAME));
ec_neg1(mkdir(change(NAME),PERM_DIRECTORY))
ec_false(walk(path,entry)) if(path[0]!='.')pop(path); distance--; } else{ for(j=1;j<distance;j++) printf("\t"); push(path); printf("%s to %s\n",NAME,change(NAME)); ec_false(filecopy(path,change(NAME))) pop(path); } return true; FIX(return false;) }
static bool push(char*s) { char*p; p=s; if(*ptr!='/'&&s[0]!='/')*ptr++='/';
while(*p) *ptr++=*p++; *ptr='\0'; if(ptr-NAME<100)return true; return false; }
static bool pop(char*path) { int i=strlen(path); if(*ptr=='/')ptr--; while(i-->=0) ptr--; if(ptr!=NAME)*ptr='\0';
if(ptr>NAME)return true; return false; }
static char *change(char*overpath) /*将完整的源文件名称转换为完整的目标文件名称*/ { char *result=(char*)malloc(SIZE*sizeof(char)),*p1,*p2; strcpy(result,obj);
p1=overpath; p2=src; while(*p2++)p1++;
strcat(result,p1); return result; }
简单介绍一下各个函数: main函数:处理命令行变元,产生源文件的根目录和目标文件的根目录;特别的,假如源文件的根目录以“.”表示的话,要用getcwd(获取当前路径)的返回值来替换。 entry函数(进行核心工作): 对一个文件进行如下工作: (1)是一个目录,那么将名称入栈,调用walk函数遍历之,并向屏幕输出待复制的源目录和目标目录,遍历完以后名称要出栈;如果可能,复制目录 (2)是一个文件,除了不遍历,其他相同; walk函数:用func所指向的回调函数(其实就是entry函数)遍历一个目录 注意:entry函数和walk函数互相调用,构成递归 push函数和pop函数:将给定的文件/目录名字出栈或者入栈,构成一个完整的路径名 change函数:根据给点的源文件根目录和目标文件根目录,将一个完整的源路径名称转换为一个完整的目标文件名称。
|