linux C文件到文件,文件到文件夹,文件夹到文件夹的拷贝

时间:2022-03-09 21:39:44
来源于高级程序设计 杨宗德(第三版)

在linux平台上运行,分享给大家。

#include <stdio.h>

#include <stdlib.h>

#include <sys/stat.h>

#include <errno.h>

#include <string.h>

#include <dirent.h>



void cp_file(const char *src,const char *dst,mode_t mode);

void cp_dir(const char *src,const char *dst);



int main(int argc,char *argv[])

{

	if(argc != 3)            //判断输入的参数个数

	{

		printf("usage:%s fp_src fp_dst\n",argv[1] );

		exit(EXIT_FAILURE);

	}



	struct stat stat_src;

	if(stat(argv[1],&stat_src) == -1)        //判断源文件的属性

	{

		perror("stat_src");

		exit(EXIT_FAILURE);

	}



	if(S_ISREG(stat_src.st_mode))    //如果源文件是文件类型

	{

		struct stat stat_dst;

		if(stat(argv[2],&stat_dst) == -1)         //判断目标文件属性

		{

			if(errno == ENOENT)          //如果判断目标文件失败的原因是因为目标文件不存在

				cp_file(argv[1],argv[2],stat_src.st_mode);           //创建目标文件,执行文件拷贝

			else

			{

				perror("file:stat_dst");

				exit(EXIT_FAILURE);	

			}			

		}



		if(S_ISREG(stat_dst.st_mode))        //如果目标文件是文件属性,说明目标文件已经存在

		{

			printf("The file is exist,do you want to overwrite it?(y/n)\n");

			char c;

			c = getchar();

			if(c == 'y' || c == 'Y')

			{

				unlink(argv[2]);

				cp_file(argv[1],argv[2],stat_src.st_mode);

			}

			else if(c == 'n' || c == 'N')

			{

				printf("The dst file do not overwrite!\n");

				return 0;

			}

			else

			{

				printf("Enter error!\n");

				exit(EXIT_FAILURE);

			}

		}



		if(S_ISDIR(stat_dst.st_mode))       //如果目标文件是文件夹属性

		{

			char *ptr = malloc(strlen(argv[2]) + 1 + strlen(argv[1]) + 1);     //创建一个目标路径,将源文件拷贝到目标文件夹下

			sprintf(ptr,"%s/%s\0",argv[2],argv[1]);

			cp_file(argv[1],ptr,stat_src.st_mode);

			free(ptr);

		}

	}



	else if(S_ISDIR(stat_src.st_mode))           //源文件是文件夹属性

	{

		struct stat stat_dst;

		if(stat(argv[2],&stat_dst) == -1)

		{

			if(errno == ENOENT)         //目标文件属性判断失败是因为目标文件不存在

			{

				if(mkdir(argv[2],stat_src.st_mode) == -1)      //创建目标文件夹,权限与源文件权限相同

				{

					perror("mkdir stat_dst");

					exit(EXIT_FAILURE);

				}

				cp_dir(argv[1],argv[2]);      //执行文件夹到文件夹的拷贝

			}

			else          //目标文件属性判断失败是因为其他原因,则退出程序

			{

				perror("dir:stat_dst");

				exit(EXIT_FAILURE);

			}

		}



		if(S_ISREG(stat_dst.st_mode))        //目标文件是文件属性

		{

			printf("Can not copy a file to a directory!\n");

			exit(EXIT_FAILURE);

		}



		if(S_ISDIR(stat_dst.st_mode))      //目标文件是已经存在的文件夹属性

		{

			char *ptr = malloc(strlen(argv[1]) + 1 +strlen(argv[2]) + 1);     //创建拷贝路径,将源文件拷贝到目标文件夹内部

			sprintf(ptr,"%s/%s\0",argv[2],argv[1]);

			printf("ptr = %s",ptr);

			if(mkdir(ptr,stat_src.st_mode) == -1)  //在目标文件内部创建新的文件夹,即与源文件相同名称和权限的文件夹

			{

				perror("mkdir ptr");

				exit(EXIT_FAILURE);

			}



			cp_dir(argv[1],ptr);

			free(ptr);

		}

	}

	return 0;

}



void cp_file(const char *src,const char *dst,mode_t mode)    //文件到文件的拷贝

{

	FILE *fp_src = NULL;

	FILE *fp_dst = NULL;



	if((fp_src = fopen(src,"r")) == NULL)

	{

		perror("fopen src");

		exit(EXIT_FAILURE);

	}

	if((fp_dst = fopen(dst,"w")) == NULL)

	{

		perror("fopen dst");

		exit(EXIT_FAILURE);

	}



	char buf[128];

	int ret = 0;

	while(1)        //循环读取源文件信息

	{

		memset(buf,'\0',128);

		ret = fread(buf,1,127,fp_src);

		fwrite(buf,1,ret,fp_dst);

		if(ret <= 0)

			break;

	}	

	fclose(fp_src);

	fclose(fp_dst);

}



void cp_dir(const char *src,const char *dst)             //文件夹到文件夹的拷贝

{

	DIR *fp_src = NULL;



	if((fp_src = opendir(src)) == NULL)

	{

		perror("opendir fp_src");

		exit(EXIT_FAILURE);

	}



	struct dirent *fp = NULL;



	while((fp = readdir(fp_src)) != NULL)

	{

		if(strcmp(fp->d_name,".") == 0 || strcmp(fp->d_name,"..") == 0)

			continue;



		char *name_src = malloc(strlen(src) + 1 + strlen(fp->d_name) + 1);    //用一个指针指向源文件夹内部的文件的路径

		sprintf(name_src,"%s/%s\0",src,fp->d_name);



		char *name_dst = malloc(strlen(dst) + 1 + strlen(fp->d_name) + 1);

		sprintf(name_dst,"%s/%s\0",dst,fp->d_name);

		

		struct stat stat_src;

		if(stat(name_src,&stat_src) == -1)

		{

			perror("name_src");

			exit(EXIT_FAILURE);

		}



		if(S_ISREG(stat_src.st_mode))

		{

			cp_file(name_src,name_dst,stat_src.st_mode);

			free(name_src);

			free(name_dst);

		}



		if(S_ISDIR(stat_src.st_mode))

		{

			if(mkdir(name_dst,stat_src.st_mode) == -1)

			{

				perror("mkdir name_dst");

				exit(EXIT_FAILURE);

			}	

			cp_dir(name_src,name_dst);

			free(name_src);

			free(name_dst);

		}

	}

}