linux 实现cp命令递归复制

  1 #include<func.h>
  2 
  3 #define LENGTH 4096
  4 
  5 int DFS_copy(char* path1, char* path2);  //递归复制
  6 
  7 int main(int argc, char* argv[]) {
  8     ARGS_CHECK(argc, 3); //检查参数是否错误
  9 
 10     struct stat statbuf;
 11     stat(argv[1], &statbuf);
 12     if (S_ISDIR(statbuf.st_mode)) { //若参数1是目录,直接进行递归
 13         DFS_copy(argv[1], argv[2]);
 14 
 15     }
 16     else { //否则参数1就是普通文件
 17         stat(argv[2], &statbuf);
 18         if (S_ISDIR(statbuf.st_mode)) { //若参数2是目录
 19             char newpath1[1024] = { 0 };
 20             char newpath2[1024] = { 0 };
 21             sprintf(newpath1, "%s", argv[1]);//重建待复制的源文件的地址
 22             sprintf(newpath2, "%s%s%s", argv[2], "/", argv[1]);//重建目的文件的地址
 23 
 24             int fdr = open(newpath1, O_RDONLY); //只读方式打开源文件
 25             ERROR_CHECK(fdr, -1, "open fdr");
 26             int fdw = open(newpath2, O_WRONLY | O_CREAT | O_TRUNC, 0666);//只写方式打开目的文件,若不存在就创建,给予权限0666
 27             ERROR_CHECK(fdw, -1, "open fdw");
 28             char buf[4096] = { 0 }; //数据缓存
 29             while (1) {
 30                 memset(buf, 0, sizeof(buf)); //每次清空内容
 31                 int ret = read(fdr, buf, sizeof(buf)); //读内容,返回成功读到的字节数
 32                 if (ret == 0) {
 33                     break;
 34                 }
 35                 write(fdw, buf, ret); //写入到目的文件
 36             }
 37             close(fdr); //关闭文件
 38             close(fdw);
 39         }
 40         else { //若参数2是普通文件,则就是两个普通文件的复制
 41             int fdr = open(argv[1], O_RDONLY); //只读方式打开源文件
 42             ERROR_CHECK(fdr, -1, "open fdr");
 43             int fdw = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);//只写方式打开目的文件,若不存在就创建,给予权限0666
 44             ERROR_CHECK(fdw, -1, "open fdw");
 45             char buf[4096] = { 0 }; //数据缓存
 46             while (1) {
 47                 memset(buf, 0, sizeof(buf)); //每次清空内容
 48                 int ret = read(fdr, buf, sizeof(buf)); //读内容,返回成功读到的字节数
 49                 if (ret == 0) {
 50                     break;
 51                 }
 52                 write(fdw, buf, ret); //写入到目的文件
 53             }
 54             close(fdr); //关闭文件
 55             close(fdw);
 56         }
 57 
 58     }
 59 
 60     return 0;
 61 }
 62 
 63 int DFS_copy(char* path1, char* path2) {
 64     DIR* pdir1 = opendir(path1); //打开源目录流
 65     ERROR_CHECK(pdir1, NULL, "opendir1"); //检查返回值是否出错
 66     if (NULL == opendir(path2)) { //打开目的文件的目录流,若不是目录就创建文件夹
 67         int ret = mkdir(path2, 0777); //创建目的文件夹
 68         ERROR_CHECK(ret, -1, "mkdir");
 69     }
 70     DIR* pdir2 = opendir(path2); //打开目的文件夹的目录流
 71     ERROR_CHECK(pdir2, NULL, "opendir2"); //检查返回值是否出错
 72     struct dirent* pdirent; //存储目录项信息
 73     while ((pdirent = readdir(pdir1)) != NULL) {  //遍历所有目录项
 74         //过滤.和..目录,不然复制的时候会死循环
 75         if (strcmp(pdirent->d_name, ".") == 0 || strcmp(pdirent->d_name, "..") == 0) {
 76             continue;
 77         }
 78 
 79         char newpath1[1024] = { 0 };
 80         char newpath2[1024] = { 0 };
 81         sprintf(newpath1, "%s%s%s", path1, "/", pdirent->d_name);//重建待复制的源文件的地址
 82         sprintf(newpath2, "%s%s%s", path2, "/", pdirent->d_name);//重建目的文件的地址
 83         if (pdirent->d_type == DT_DIR) { //判断当前目录项是否是个目录
 84             DFS_copy(newpath1, newpath2); //是目录就进行递归复制
 85         }
 86         else { //不是目录就直接复制
 87         //------------------read/write方式复制文件------------------
 88             // int fdr = open(newpath1, O_RDONLY); //只读方式打开源文件
 89             // ERROR_CHECK(fdr, -1, "open fdr");
 90             // int fdw = open(newpath2, O_WRONLY | O_CREAT | O_TRUNC, 0666);//只写方式打开目的文件,若不存在就创建,给予权限0666
 91             // ERROR_CHECK(fdw, -1, "open fdw");
 92             // char buf[4096] = { 0 }; //数据缓存
 93             // while (1) {
 94             //     memset(buf, 0, sizeof(buf)); //每次清空内容
 95             //     int ret = read(fdr, buf, sizeof(buf)); //读内容,返回成功读到的字节数
 96             //     if (ret == 0) {
 97             //         break;
 98             //     }
 99             //     write(fdw, buf, ret); //写入到目的文件
100             // }
101             // close(fdr); //关闭文件
102             // close(fdw);
103         //--------------------------------------------------------
104         //------------------mmap方式复制文件-----------------------
105             int fdr = open(newpath1, O_RDONLY);
106             ERROR_CHECK(fdr, -1, "open fdr");
107             int fdw = open(newpath2, O_RDWR | O_CREAT | O_TRUNC, 0666);
108             ERROR_CHECK(fdw, -1, "open fdw");
109 
110             struct stat statbuf;
111             fstat(fdr, &statbuf); //和stat函数一样,只是参数变为文件描述符
112             ftruncate(fdw, statbuf.st_size);
113             off_t fsize = 0;
114             int cp_size;
115             while (fsize < statbuf.st_size) {
116                 if (statbuf.st_size - fsize >= LENGTH) {
117                     cp_size = LENGTH;
118                 }
119                 else {
120                     cp_size = statbuf.st_size - fsize;
121                 }
122 
123                 char* src = (char*)mmap(NULL, cp_size, PROT_READ, MAP_SHARED, fdr, fsize);
124                 ERROR_CHECK(src, MAP_FAILED, "mmap");
125 
126                 char* dest = (char*)mmap(NULL, cp_size, PROT_WRITE | PROT_READ, MAP_SHARED, fdw, fsize);
127                 ERROR_CHECK(dest, MAP_FAILED, "mmap");
128 
129                 memcpy(dest, src, cp_size);
130                 // for(int i = 0; i < cp_size; i++){  //另一种转移数据的方式
131                 //     dest[i] = src[i];
132                 // }
133                 munmap(src, cp_size);
134                 munmap(dest, cp_size);
135                 fsize += cp_size;
136             }
137 
138             //--------------------------------------------------------
139         }
140     }
141     closedir(pdir1); //关闭目录流
142     closedir(pdir2);
143     return 0;
144 }

 

posted @ 2022-05-15 20:05  烛爻  阅读(549)  评论(0编辑  收藏  举报