来源于高级程序设计 杨宗德(第三版)
在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);
}
}
}