Linux&C编程之Linux系统命令“cp -r”的简单实现
来源:互联网 发布:手机淘宝店铺页面 编辑:程序博客网 时间:2024/06/04 18:52
关于会用到的文件与目录的一些基本函数可参考:
Linux&C编程之Linux系统命令“ls -l”的简单实现
一、测试结果:
二、源代码:
1、自定义头文件copy.h:
/*copy.h*/#ifndef _COPY_H_#define _COPY_H_#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <dirent.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>/*复制文件时的读写缓冲区大小*/#define BUF_SIZE 8092/*保存文件路径的缓冲区大小*/#define PATH_SIZE 1024/*文件权限*/#define FILE_MODE 0664/*目录权限*/#define DIR_MODE 0664void sys_err(const char *); /*errno错误处理*/void deal_dir(const char *,const char *); /*递归函数,处理目录*/void deal_copy(const char *,const char *); /*处理绝对路径的文件*/void read_write(void); /*拷贝文件时的读写操作*/void mkdir_newdir(const char *); /*为目标创建空目录*/void get_allpath(char *,char *,const char *,const char *); /*获取source与target的绝对路径*/void init_allpath(char *,char *,char *,char *,const char *); /*清空存储路径与文件名的缓冲区并重新赋值*/#endif
2、函数实现copy.c:
/*copy.c*/#include<copy.h>/**将读source与写target的文件描述读定义成全局变量*fd[0] == fd_read*fd[1] == fd_write*/int fd[2] = {0};void sys_err(const char * ptr){ perror(ptr); exit(EXIT_FAILURE);}void deal_dir(const char *old_path,const char * new_path){ DIR * ret_opdir = opendir(old_path);//打开目录 if(ret_opdir == NULL) sys_err("opendir"); struct dirent * ret_redir; /*定义缓冲区存放绝对路径,eg:/home/krj/test/*/ char buf_old[PATH_SIZE] = {}; char buf_new[PATH_SIZE] = {}; /*存放绝对路径+文件名,eg:/home/krj/test/test.txt*/ char buf_oldfile[PATH_SIZE] = {}; char buf_newfile[PATH_SIZE] = {}; /*获取源文件完整路径与目标位置完整路径,分别存入buf_old与buf_new中*/ get_allpath(buf_old, buf_new, old_path, new_path); while((ret_redir = readdir(ret_opdir))){//读取目录,失败或目录读完返回NULL if(!strcmp(ret_redir->d_name, ".") || !strcmp(ret_redir->d_name, "..")) continue; else{ /*清除上次复制的文件路径,并填入新读取到的文件的路径*/ init_allpath(buf_old, buf_new, buf_oldfile, buf_newfile, ret_redir->d_name); if((ret_redir->d_type & DT_REG) == DT_REG)//如果读到的文件是普通文件则复制 deal_copy(buf_oldfile, buf_newfile); else if((ret_redir->d_type & DT_DIR) == DT_DIR)//如果读到的是目录则递归处理目录 deal_dir(buf_oldfile, buf_newfile); } }}void get_allpath(char * buf_old, char * buf_new, const char * old_path, const char * new_path){ char buf[PATH_SIZE] = {};/*存放当前路径*/ getcwd(buf,PATH_SIZE);/*获取当前路径*/ chdir(old_path);/*改变路径到source*/ getcwd(buf_old,PATH_SIZE);/*获取source的绝对路径*/ strcat(buf_old, "/");/*加上“/”以方便之后向buf_oldfile中补上具体文件名*/ chdir(buf);/*回到原来目录*/ /*与获取source绝对路径相同,获取target绝对路径,当然两次获取可以简化成一个函数,由于代码不是太多就没过多简化*/ mkdir_newdir(new_path);//先创建一个空目录 chdir(new_path); getcwd(buf_new, PATH_SIZE); strcat(buf_new,"/");}void init_allpath(char * buf_old, char * buf_new, char * buf_oldfile, char * buf_newfile, const char * name){ /*清空source与target的带文件名的绝对路径缓冲区*/ memset(buf_oldfile, 0, PATH_SIZE); memset(buf_newfile, 0, PATH_SIZE); /*将source的缓冲区更新为最新读到的source文件*/ strcpy(buf_oldfile, buf_old); strcat(buf_oldfile, name); /*同上理*/ strcpy(buf_newfile, buf_new); strcat(buf_newfile, name);}void mkdir_newdir(const char * new_path){ /*目录不存在返回NULL,则创建空目录*/ DIR * ret_opdir = opendir(new_path); if(ret_opdir == NULL){ int ret_mkdir = mkdir(new_path, DIR_MODE);/*创建子目录*/ if(ret_mkdir == -1) sys_err("mkdir newdir"); }}void deal_copy(const char *old_file,const char * pathname){ struct stat get_message; int ret_stat = stat(pathname, &get_message); if(ret_stat == -1 && errno != ENOENT)//文件信息读取失败,并且不是因为无该文件造成的 sys_err("stat in copy.c of deal_copy"); fd[0] = open(old_file, O_RDONLY);/*打开source文件*/ if(fd[0] == -1) sys_err("open oldfile in copy_file"); fd[1] = open(pathname, O_CREAT | O_TRUNC | O_RDWR, FILE_MODE);/*创建并打开target文件*/ if(fd[1] == -1) sys_err("open newfile in copy_file"); read_write();/*进行source的读与对应的target的写(复制)*/ close(fd[0]); close(fd[1]);} void read_write(void){ char buf[BUF_SIZE] = {}; int ret_read, ret_write; while((ret_read = read(fd[0], buf, BUF_SIZE)) > 0){/*读到EOF时返回0结束*/ ret_write = write(fd[1], buf, strlen(buf)); /*等效于ret_write = write(fd[1], buf, ret_read);*/ if(ret_write == -1) sys_err("write newfile"); }}
3、主函数main.c:
/*******文件名:main.c*时间:2017/2/18-19:57*功能:实现简单的目录文件拷贝*限定测试格式:mycp -r source target或:mycp -R source target*局限性:不能使用正则,功能有限******/#include<copy.h>int main(int argc, char ** argv){ if(argc != 4){ printf("too few or lost parameter!\n"); exit(EXIT_FAILURE); } else if(!strcmp(argv[1], "-r") || !strcmp(argv[1], "-R")){ struct stat get_message; int ret_stat = stat(argv[2],&get_message); if(ret_stat == -1) sys_err("stat argv[2]"); if(S_ISDIR(get_message.st_mode)) deal_dir(argv[2],argv[3]);//如果argv[2]是目录则按目录递归处理 else{//否则按照文件直接复制,局限性:复制单个文件时只能向当前目录复制 if(strcmp(argv[2],argv[3]) == 0){ printf("The same filename of parameter is error!\n"); exit(EXIT_FAILURE); } deal_copy(argv[2],argv[3]); } } return 0;}
0 0
- Linux&C编程之Linux系统命令“cp -r”的简单实现
- Linux系统编程之模拟命令cp
- Linux&C编程之Linux系统命令“ls -l”的简单实现
- Linux C系统编程:使用线程池,实现cp功能
- linux 的cp命令实现
- linux cp 命令的实现
- linux下实现cp -r的经验
- 系统调用实现Linux命令 cp
- 【C语言】实现Linux下的cp命令的基本功能
- C语言实现Linux cp命令
- linux下cp命令---C代码实现
- linux cp 命令实现
- linux命令实现:cp
- Linux 实现cp 命令
- Linux C编程连载(1)-cp的实现
- Linux C编程连载【1】-cp的实现
- linux命令之cp
- Linux命令之"cp"
- JAVA动态代理实例
- 第一章:快速改造 基础知识
- CodeForces - 744A Hongcow Builds A Nation
- 为什么用接口(一)
- Express框架学习总结
- Linux&C编程之Linux系统命令“cp -r”的简单实现
- 基于BP神经网络的数字识别基础系统(一)
- 相对布局知识小结
- VB6.0操作SQL Server——增删改查
- 移植库需要注意事项(与移植库生成的文件如何使用)
- 【匈牙利算法】二分图最大匹配(模板)
- hdu1232 通畅工程讲解(并查集)
- oj1944: C语言实验——格式化输出(常量练习)
- 单片机双色点阵显示特定图形