#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]);
/*確定源文件的根目錄和目標(biāo)文件的根目錄*/
ec_false(entry(argv[1]))
/*從源文件的根目錄開始工作*/
return 0;
FIX(return 1;)
}
static bool walk(char*path,bool(*func)(char*)) /*遍歷一個(gè)目錄,對其每個(gè)項(xiàng)目使用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))/*當(dāng)前目錄為待遍歷的目錄,先記錄,再跳轉(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)換為完整的目標(biāo)文件名稱*/
{
char *result=(char*)malloc(SIZE*sizeof(char)),*p1,*p2;
strcpy(result,obj);
p1=overpath;
p2=src;
while(*p2++)p1++;
strcat(result,p1);
return result;
}
簡單介紹一下各個(gè)函數(shù):
main函數(shù):處理命令行變元,產(chǎn)生源文件的根目錄和目標(biāo)文件的根目錄;特別的,假如源文件的根目錄以“.”表示的話,要用getcwd(獲取當(dāng)前路徑)的返回值來替換。
entry函數(shù)(進(jìn)行核心工作):
對一個(gè)文件進(jìn)行如下工作:
(1)是一個(gè)目錄,那么將名稱入棧,調(diào)用walk函數(shù)遍歷之,并向屏幕輸出待復(fù)制的源目錄和目標(biāo)目錄,遍歷完以后名稱要出棧;如果可能,復(fù)制目錄
(2)是一個(gè)文件,除了不遍歷,其他相同;
walk函數(shù):用func所指向的回調(diào)函數(shù)(其實(shí)就是entry函數(shù))遍歷一個(gè)目錄
注意:entry函數(shù)和walk函數(shù)互相調(diào)用,構(gòu)成遞歸
push函數(shù)和pop函數(shù):將給定的文件/目錄名字出?;蛘呷霔#瑯?gòu)成一個(gè)完整的路徑名
change函數(shù):根據(jù)給點(diǎn)的源文件根目錄和目標(biāo)文件根目錄,將一個(gè)完整的源路徑名稱轉(zhuǎn)換為一個(gè)完整的目標(biāo)文件名稱。