#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函數(shù)*/ { DIR *sp=NULL; struct dirent *bp; int fd=-1; struct stat st;
ec_null(sp=opendir(path)) ec_neg1(fd=open(".",O_RDONLY))/*當前目錄為待遍歷的目錄,先記錄,再跳轉(zhuǎn)*/ 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) /*將完整的源文件名稱轉(zhuǎn)換為完整的目標文件名稱*/ { char *result=(char*)malloc(SIZE*sizeof(char)),*p1,*p2; strcpy(result,obj);
p1=overpath; p2=src; while(*p2++)p1++;
strcat(result,p1); return result; }
簡單介紹一下各個函數(shù): main函數(shù):處理命令行變元,產(chǎn)生源文件的根目錄和目標文件的根目錄;特別的,假如源文件的根目錄以“.”表示的話,要用getcwd(獲取當前路徑)的返回值來替換。 entry函數(shù)(進行核心工作): 對一個文件進行如下工作: (1)是一個目錄,那么將名稱入棧,調(diào)用walk函數(shù)遍歷之,并向屏幕輸出待復制的源目錄和目標目錄,遍歷完以后名稱要出棧;如果可能,復制目錄 (2)是一個文件,除了不遍歷,其他相同; walk函數(shù):用func所指向的回調(diào)函數(shù)(其實就是entry函數(shù))遍歷一個目錄 注意:entry函數(shù)和walk函數(shù)互相調(diào)用,構(gòu)成遞歸 push函數(shù)和pop函數(shù):將給定的文件/目錄名字出棧或者入棧,構(gòu)成一個完整的路徑名 change函數(shù):根據(jù)給點的源文件根目錄和目標文件根目錄,將一個完整的源路徑名稱轉(zhuǎn)換為一個完整的目標文件名稱。
|