文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>实现cp命令–文件夹的拷贝

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

时间:2010-07-29  来源:edsionte

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

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

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

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

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

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

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

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

void cp_directory(char* original_src_path,char* original_dest_path)
{
        struct stat buf;
        DIR *dir;
        struct dirent *ptr;
        char path[PATH_MAX+1];
        char src_path[PATH_MAX+1],dest_path[PATH_MAX+1];

        strcpy(src_path,original_src_path);
        strcpy(dest_path,original_dest_path);

        if(src_path[strlen(src_path)-1]!='/')
        {
                strncat(src_path,"/",1);
        }
        //the following code be omited
}

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

if(stat(dest_path,&buf)==-1)
        {
                //create a directory which name is dest_path
                stat(src_path,&buf);
                if(mkdir(dest_path,buf.st_mode)==-1)
                {
                        printf("my_cp:create the directory \"%s\" error.\n",dest_path);
                        return ;
                }
        }
        else
        {
                //exist
                if(!S_ISDIR(buf.st_mode))
                {
                        printf("my_cp:the directory \"%s\" can't cover the no-directory \"%s\".\n",src_path,dest_path);
                        return ;
                }
                else
                {
                        if(dest_path[strlen(dest_path)-1]!='/')
                        {
                                strncat(dest_path,"/",1);
                        }
                        //extract the lowest directory
                        int i,k=0;
                        char lowestdir[PATH_MAX+1];
                        for(i=strlen(src_path)-1-1;i>\0;i--)
                        {
                                if(src_path[i]=='/')
                                {
                                        i=i+1;
                                        break;
                                }
                        }

                        for(;i<\strlen(src_path);i++)
                        {
                                lowestdir[k++]=src_path[i];
                        }
                        strncat(dest_path,lowestdir,strlen(lowestdir));
                        struct stat temp_buf;
                        char temp_path[PATH_MAX+1]="rm -rf ";
                        if(stat(dest_path,&temp_buf)==0)
                        {
                                strcat(temp_path,dest_path);
                                system(temp_path);
                        }
                        if(mkdir(dest_path,buf.st_mode)==-1)
                        {
                                printf("my_cp:create the directory \"%s\" error.\n",dest_path);
                                return ;
                        }
                }
        }

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

    if((dir=opendir(src_path))==NULL)
        {
                printf("my_cp:open the srouce path \"%s\" error.\n",src_path);
                return ;
        }
        char temp_dest_path[PATH_MAX+1];
        strcpy(temp_dest_path,dest_path);
        while((ptr=readdir(dir))!=NULL)
        {
                if(!strcmp(ptr->\d_name,"."))
                        continue;
                if(!strcmp(ptr->\d_name,".."))
                        continue;
                strcpy(path,src_path);
                strcat(path,ptr->\d_name);
                if(stat(path,&buf)==-1)
                {
                        printf("my_cp:open the file \"%s\" error.\n",path);
                        return ;
                }
                strcpy(dest_path,temp_dest_path);
                //get the right dest_path
                if(S_ISDIR(buf.st_mode))
                {
                        cp_directory(path,dest_path);
                }
                else
                {
                        cp_single(path,dest_path);
                }
        }

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

以上就是my_cp函数的实现过程,源码在这里。如果发现了不妥之处,欢迎指正。

排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载