Chinaunix首页 | 论坛 | 博客
  • 博客访问: 57390
  • 博文数量: 22
  • 博客积分: 1546
  • 博客等级: 上尉
  • 技术积分: 230
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-20 20:33
文章分类
文章存档

2010年(22)

分类: C/C++

2010-07-29 15:40:28

刚刚完成了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函数的实现过程,源码在。如果发现了不妥之处,欢迎指正。

阅读(1838) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~