[LinuxC]_02_递归拷贝文件夹

15 篇文章 0 订阅

新更新的代码

2021/04/29:更新:使用string代替原先的malloc内存申请

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

/**
 * @brief: 判断当前路径是否为目录,使用stat()函数
 * @return {*}
 * @note: 
 * @param {string} &path
 */
int is_dir(string &path){//判断是否是目录
	struct stat st;
	stat(path.c_str(),&st);
	if(S_ISDIR(st.st_mode)){
		return 1;
	}
	else{
		return 0;
	}
}


/**
 * @brief: 判断字符串最后一个字符是否和c一致,主要用于判断字符串结尾是否为“/”
 * @return {*}
 * @note: 
 * @param {string} &s
 * @param {char} c
 */
int endwith(string &s,char c){//用于判断字符串结尾是否为“/”
	if(s[s.size() - 1]==c){
		return 1;
	}
	else{
		return 0;
	}
}



/**
 * @brief: 字符串连接函数
 * @return {*}
 * @note: 
 * @param {const string} &str1
 * @param {const string} &str2
 */
string str_contact(const string &str1,const string &str2){
	stringstream tmp_path;
	tmp_path << str1 << str2;
	return tmp_path.str();
}


/**
 * @brief: 复制文件
 * @return {*}
 * @note: 
 * @param {string} &source_path 原路径
 * @param {string} &destination_path 目的路径
 */
void copy_file(const string &source_path,const string &destination_path){
	char buffer[1024];
	FILE *in,*out;//定义两个文件流,分别用于文件的读取和写入int len;
	if((in=fopen(source_path.c_str(),"r"))==NULL){//打开源文件的文件流
		printf("源文件打开失败!\n");
		exit(1);
	}
	if((out=fopen(destination_path.c_str(),"w"))==NULL){//打开目标文件的文件流
		printf("目标文件创建失败!\n");
		exit(1);
	}
	int len;//len为fread读到的字节长
	while((len=fread(buffer,1,1024,in))>0){//从源文件中读取数据并放到缓冲区中,第二个参数1也可以写成sizeof(char)
		fwrite(buffer,1,len,out);//将缓冲区的数据写到目标文件中
	}
	fclose(out);
	fclose(in);
}



/**
 * @brief: 文件夹复制
 * @return {*}
 * @note: 
 * @param {string} &source_path
 * @param {string} &destination_path
 */
void copy_folder(string &source_path,string &destination_path){//复制文件夹
	if(!opendir(destination_path.c_str())){
		//如果目标目录不存在就用mkdir函数来创建
		if (mkdir(destination_path.c_str(),0777))
		{
		    printf("创建文件夹失败!");
		}
	}

    struct dirent* filename;
    printf("source_path = %s\n",source_path.c_str());

	DIR* dp=opendir(source_path.c_str());			//用DIR指针指向这个文件夹
	while(filename=readdir(dp)){			//遍历DIR指针指向的文件夹,也就是文件数组。
		string path;
		path = str_contact(path,source_path);
		//如果source_path,destination_path以路径分隔符结尾,那么source_path/,destination_path/直接作路径即可 
		//否则要在source_path,destination_path后面补个路径分隔符再加文件名,谁知道你传递过来的参数是f:/a还是f:/a/啊?
		string file_source_path;
		
		if(!endwith(source_path,'/')){
			file_source_path=str_contact(file_source_path,source_path);
			file_source_path=str_contact(source_path,"/");
		}
		else{
			file_source_path=str_contact(file_source_path,source_path);
		}

		string file_destination_path;
		if(!endwith(destination_path,'/')){
			file_destination_path=str_contact(file_destination_path,destination_path);
			file_destination_path=str_contact(destination_path,"/");
		}
		else{
			file_destination_path=str_contact(file_destination_path,destination_path);
		}

		//取文件名与当前文件夹拼接成一个完整的路径
		file_source_path=str_contact(file_source_path,filename->d_name);
		file_destination_path=str_contact(file_destination_path,filename->d_name);
		if(is_dir(file_source_path)){//如果是目录
			if(!endwith(file_source_path,'.')){//同时并不以.结尾,因为Linux在所有文件夹都有一个.文件夹用于连接上一级目录,必须剔除,否则进行递归的话,后果无法相像
				copy_folder(file_source_path,file_destination_path);//进行递归调用,相当于进入这个文件夹进行复制~
			}		
		}
		else{
			copy_file(file_source_path,file_destination_path);//否则按照单一文件的复制方法进行复制。
			printf("复制%s到%s成功!\n",file_source_path.c_str(),file_destination_path.c_str());
		}
	}	
}



/*主函数*/
int main(int argc,char *argv[]){
    string source_path = "/home/tianyiyi/workspace/copy_dir/src";
    string destination_path = "/home/tianyiyi/workspace/copy_dir/dst";
	
	// 测试函数
	string src_path = "/home/tianyiyi/workspace/copy_dir/src";
	cout << is_dir(src_path);
	cout << endwith(src_path,'/');

	cout << str_contact(source_path,destination_path);

	copy_file("/home/tianyiyi/workspace/copy_dir/src/a.cpp","/home/tianyiyi/workspace/copy_dir/src/a.h");

 	 // 这个是文件夹复制函数的入口
	copy_folder(source_path,destination_path);//进行文件夹的拷贝
	return 0;
}




目前此代码有指针未释放,待完善,慎用、

2021/04/20 :这个是旧代码。如果使用此功能,请参考上面的代码
原网址链接

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include "app_file.h"


int is_dir(char* path){//判断是否是目录
	struct stat st;
	stat(path,&st);
	if(S_ISDIR(st.st_mode)){
		return 1;
	}
	else{
		return 0;
	}
}
/*字符串处理函数*/
int endwith(char* s,char c){//用于判断字符串结尾是否为“/”
	if(s[strlen(s)-1]==c){
		return 1;
	}
	else{
		return 0;
	}
}
char* str_contact(char* str1,char* str2){//字符串连接
	char* result;
	result=(char*)malloc(strlen(str1)+strlen(str2)+1);//str1的长度+str2的长度+\0;
	if(!result){//如果内存动态分配失败
		printf("字符串连接时,内存动态分配失败\n");
		exit(1);
	}
    memset(result,0,sizeof(result));
    strcat(result,str1);
	strcat(result,str2);//字符串拼接
	return result;
}
/*复制函数*/
void copy_file(const char* source_path,const char *destination_path){//复制文件
	char buffer[1024];
	_LOG_DEBUG("source_path = %s",source_path);
	_LOG_DEBUG("destination_path = %s",destination_path);
	FILE *in,*out;//定义两个文件流,分别用于文件的读取和写入int len;
	if((in=fopen(source_path,"r"))==NULL){//打开源文件的文件流
		printf("源文件打开失败!\n");
		exit(1);
	}
	if((out=fopen(destination_path,"w"))==NULL){//打开目标文件的文件流
		printf("目标文件创建失败!\n");
		exit(1);
	}
	int len;//len为fread读到的字节长
	while((len=fread(buffer,1,1024,in))>0){//从源文件中读取数据并放到缓冲区中,第二个参数1也可以写成sizeof(char)
		fwrite(buffer,1,len,out);//将缓冲区的数据写到目标文件中
	}
	fclose(out);
	fclose(in);
}
void copy_folder(char* source_path,char *destination_path){//复制文件夹
	if(!opendir(destination_path)){
		if (mkdir(destination_path,0777))//如果不存在就用mkdir函数来创建
		{
		    printf("创建文件夹失败!");
		}
	}
	char *path;
	path=(char*)malloc(512);//相当于其它语言的String path="",纯C环境下的字符串必须自己管理大小,这里为path直接申请512的位置的空间,用于目录的拼接
	memset(path,0,sizeof(path));
    path=str_contact(path,source_path);//这三句,相当于path=source_path
    //strncpy(path,source_path,sizeof(path));
	
    struct dirent* filename;
    _LOG_DEBUG("%s",path);
	DIR* dp=opendir(path);//用DIR指针指向这个文件夹
	while(filename=readdir(dp)){//遍历DIR指针指向的文件夹,也就是文件数组。
		memset(path,0,sizeof(path));
		path=str_contact(path,source_path);
		//如果source_path,destination_path以路径分隔符结尾,那么source_path/,destination_path/直接作路径即可 
		//否则要在source_path,destination_path后面补个路径分隔符再加文件名,谁知道你传递过来的参数是f:/a还是f:/a/啊?
		char *file_source_path;
		file_source_path=(char*)malloc(512);
		if(!endwith(source_path,'/')){
			file_source_path=str_contact(file_source_path,source_path);
			file_source_path=str_contact(source_path,"/");
		}
		else{
			file_source_path=str_contact(file_source_path,source_path);
		}
		char *file_destination_path;
		file_destination_path=(char*)malloc(512);
		if(!endwith(destination_path,'/')){
			file_destination_path=str_contact(file_destination_path,destination_path);
			file_destination_path=str_contact(destination_path,"/");
		}
		else{
			file_destination_path=str_contact(file_destination_path,destination_path);
		}
		//取文件名与当前文件夹拼接成一个完整的路径
		file_source_path=str_contact(file_source_path,filename->d_name);
		file_destination_path=str_contact(file_destination_path,filename->d_name);
		if(is_dir(file_source_path)){//如果是目录
			if(!endwith(file_source_path,'.')){//同时并不以.结尾,因为Linux在所有文件夹都有一个.文件夹用于连接上一级目录,必须剔除,否则进行递归的话,后果无法相像
				copy_folder(file_source_path,file_destination_path);//进行递归调用,相当于进入这个文件夹进行复制~
			}		
		}
		else{
			copy_file(file_source_path,file_destination_path);//否则按照单一文件的复制方法进行复制。
			printf("复制%s到%s成功!\n",file_source_path,file_destination_path);
		}
	}	
}


/**
 * @brief: 文件夹拷贝函数
 * @return {*}
 * @note: 
 * @param {string} &source_path
 * @param {string} &destination_path
 */
int copy_directory(string &source_path,string &destination_path)
{
	// if(argv[1]==NULL||argv[1]==NULL){
	// 	printf("请输入两个文件夹路径,第一个为源,第二个为目的!\n");
	// 	exit(1);
	// }
	// char* source_path=argv[1];//取用户输入的第一个参数
	// char* destination_path=argv[2];//取用户输入的第二个参数
	//DIR* source=opendir(source_path.c_str());
	//DIR* destination=opendir(destination_path.c_str());
	// if(!source||!destination){
	// 	printf("你输入的一个参数或者第二个参数不是文件夹!\n");
	// }
    char src[1024] = {0};
    char dst[1024] = {0};
    strncpy(src,source_path.c_str(),source_path.size());
    strncpy(dst,destination_path.c_str(),destination_path.size());
	copy_folder(src,dst);//进行文件夹的拷贝
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fantongl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值