实现cp命令–文件夹的拷贝

实现cp命令–文件夹的拷贝

2010年7月27日 由 edsionte留言 »

刚刚完成了my_cp的另一个功能:将一个目录拷贝到指定目录。加上昨天实现的将一个文件拷贝到指定地址下,现在已经完成了我们实现前所定下的要求。也许你会有疑问,那多个文件的拷贝的实现呢?我面前面已经说过,只要完成上述两个功能,并且你在主函数中“分流”正确,那么只要在合适的位置调用这两个函数即可,具体办法我们下面会讨论。

在详解如何实现将一个目录拷贝到指定目录(cp_directory函数)之前,我们首先应该弄明白下面的内容:

1.如果目标目录中的最低级目录不存在,则会新建这个目录,并把源目录中的所有文件拷贝到此新建的目录下。比如cp -r dir ./newdir。我们可以看到./newdir(这个路径中最低级的目录是newdir)在cp前是不存在的,但是cp后新建了这个目录,并且将dir中的所有文件拷贝到这个新建的目录下。

1 gues@huangwei-desktop:~/code/shell_command$ ls
2 cptest  ls   my_cp   my_cp.c  my_ls_plus    my_shell.c    nothisdirectory  tdir         test
3 dir     ls1  my_cp1  my_ls.c  my_ls_plus.c  newdirectory  nothisfile       tdirmy_ls.c  ttfile.c
4 gues@huangwei-desktop:~/code/shell_command$ ls dir
5 ed  my_cp1  test  ttfile.c
6 gues@huangwei-desktop:~/code/shell_command$ cp -r dir ./newdir
7 gues@huangwei-desktop:~/code/shell_command$ ls newdir
8 ed  my_cp1  test  ttfile.c

2.如果最低级的目标目录存在,则会将源目录(当然也包含源目录下的所有文件)拷贝到这个目标目录。我们仍执行上面那个命令:cp -r dir ./newdir。但是这次结果是不一样的,由于1的操作,newdir目录已经存在,这次cp后将dir目录拷贝到了已存在的newdir目录下(即./newdir/dir/)。

1 gues@huangwei-desktop:~/code/shell_command$ ls newdir
2 ed  my_cp1  test  ttfile.c
3 gues@huangwei-desktop:~/code/shell_command$ cp ./dir -r ./newdir
4 gues@huangwei-desktop:~/code/shell_command$ ls newdir
5 dir  ed  my_cp1  test  ttfile.c

如果我说的还不够明白,你也可以自己亲自验证一下cp命令。

下面我们来详解。还是先保留传递过来的路径。然后如果源文件夹不包含/,则添加。

01 void cp_directory(char* original_src_path,char* original_dest_path)
02 {
03     struct stat buf;
04     DIR *dir;
05     struct dirent *ptr;
06     char path[PATH_MAX+1];
07     char src_path[PATH_MAX+1],dest_path[PATH_MAX+1];
08  
09     strcpy(src_path,original_src_path);
10     strcpy(dest_path,original_dest_path);
11  
12     if(src_path[strlen(src_path)-1]!='/')
13     {
14         strncat(src_path,"/",1);
15     }
16         //the following code be omited
17 }

如果目标目录中最低级的目录不存在,则创建它。如果次低级目录也不存在,则在创建的时候就发生错误。如果目标目录存在,并且是目录文件,那么就如同上面举例2中所述,我们需要将源路径中最低级的目录拷贝到目标目录中。这里面设计到提提取源路径最低级的目录,以及将其连接在目标目录后等。这些都不难理解。注意当完成目标路径的拼接后,如果这个目录本身就存在,那么我们将其删除,创建新目录。

01 if(stat(dest_path,&buf)==-1)
02     {
03         //create a directory which name is dest_path
04         stat(src_path,&buf);
05         if(mkdir(dest_path,buf.st_mode)==-1)
06         {
07             printf("my_cp:create the directory \"%s\" error.\n",dest_path);
08             return ;
09         }
10     }
11     else
12     {
13         //exist
14         if(!S_ISDIR(buf.st_mode))
15         {
16             printf("my_cp:the directory \"%s\" can't cover the no-directory \"%s\".\n",src_path,dest_path);
17             return ;
18         }
19         else
20         {
21             if(dest_path[strlen(dest_path)-1]!='/')
22             {
23                 strncat(dest_path,"/",1);
24             }
25             //extract the lowest directory
26             int i,k=0;
27             char lowestdir[PATH_MAX+1];
28             for(i=strlen(src_path)-1-1;i>\0;i--)
29             {
30                 if(src_path[i]=='/')
31                 {
32                     i=i+1;
33                     break;
34                 }
35             }
36  
37             for(;i<\strlen(src_path);i++)
38             {
39                 lowestdir[k++]=src_path[i];
40             }
41             strncat(dest_path,lowestdir,strlen(lowestdir));
42             struct stat temp_buf;
43             char temp_path[PATH_MAX+1]="rm -rf ";
44             if(stat(dest_path,&temp_buf)==0)
45             {
46                 strcat(temp_path,dest_path);
47                 system(temp_path);
48             }
49                     if(mkdir(dest_path,buf.st_mode)==-1)
50                 {
51                 printf("my_cp:create the directory \"%s\" error.\n",dest_path);
52                     return ;
53                 }
54         }
55     }

接着我们打开源目录,读取其下的所有文件名。这个方法在my_ls的时候就已经使用过。我们将这些文件名与目的路径拼接后,检查他们是否是目录文件。如果是普通文件那么就调用cp_single函数,否则调用cp_directory函数。

01 if((dir=opendir(src_path))==NULL)
02 {
03     printf("my_cp:open the srouce path \"%s\" error.\n",src_path);
04     return ;
05 }
06 char temp_dest_path[PATH_MAX+1];
07 strcpy(temp_dest_path,dest_path);
08 while((ptr=readdir(dir))!=NULL)
09 {
10     if(!strcmp(ptr->\d_name,"."))
11         continue;
12     if(!strcmp(ptr->\d_name,".."))
13         continue;
14     strcpy(path,src_path);
15     strcat(path,ptr->\d_name);
16     if(stat(path,&buf)==-1)
17     {
18         printf("my_cp:open the file \"%s\" error.\n",path);
19         return ;
20     }
21     strcpy(dest_path,temp_dest_path);
22     //get the right dest_path
23     if(S_ISDIR(buf.st_mode))
24     {
25         cp_directory(path,dest_path);
26     }
27     else
28     {
29         cp_single(path,dest_path);
30     }
31 }

其实这是一个递归的过程,对于递归,最重要的是能返回到调用函数。对于任何目录,最终要么这个目录是空的,要么全是普通文件,所以肯定能返回到上一级函数中,不会无限的去嵌套。

以上就是my_cp函数的实现过程,需要源码的同学留下邮箱即可。如果发现了不妥之处,欢迎指正。

http://edsionte.com/techblog/archives/904

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值