本blog主要是模仿Linux的cp命令的功能,未实现参数,只是基础功能部分。

本文的主要目的在于练习 文件流目录流 中的函数的使用。

主要功能包括两种:

  • 源文件属性为文件,拷贝到其它文件(内容复制)或目录(作为目录子文件)
  • 源文件属性为目录,拷贝到其它目录(作为子目录存在)

其实现的流程图如下所示:

本copy我们通过三个文件来实现:

  • main.c:流程的实现
  • copy.c:拷贝功能的实现
  • copy.h:必要的头文件
  1. main.c

    /*********************************************************
    * File name:
    * Description:
    * Author: Jimmy_Nie
    * Version Modify Time
    * v1.0 creat 2017-09-12
    *
    *********************************************************/ #include "copy_file.h" int main(int argc, char *argv[])
    {
    //Check the arguments
    if( 3 != argc)
    {
    printf("%s(%d): arguments error!\n",__FILE__, __LINE__);
    exit(EXIT_FAILURE);
    } //check the source file is a file or a directory
    struct stat src_stat; //destination file check
    struct stat dest_stat; //If source is a file
    if( FILES == check_file(argv[1], &src_stat) )
    {
    FILE_ENUM dest_enum;
    dest_enum = check_file( argv[2], &dest_stat ); char cmd[100] = "";
    char ch; switch(dest_enum)
    {
    case NOT_EXIST:
    sprintf(cmd, "touch %s", argv[2]);
    system( cmd ); check_file( argv[2], &dest_stat );
    cp_file(argv[1], argv[2], &dest_stat); break; case DIRECTORY:
    cp_file(argv[1], argv[2], &dest_stat);
    break; case FILES:
    fprintf(stdout, "Overwrite the dest file %s, [y/n]\n", argv[2]);
    ch = getchar(); if( ch == 'Y' || ch == 'y' )
    {
    cp_file(argv[1], argv[2], &dest_stat);
    }
    else
    exit(0); break;
    default:
    fprintf(stderr, "%s(%d): file type error\n", __FILE__, __LINE__);
    }
    } //If source file is a directory
    else if( DIRECTORY == check_file(argv[1], &dest_stat) )
    {
    FILE_ENUM dest_enum;
    dest_enum = check_file( argv[2], &dest_stat ); char cmd[100] = ""; switch(dest_enum)
    {
    case NOT_EXIST:
    sprintf(cmd, "mkdir -p %s", argv[2]);
    system( cmd );
    cp_dir(argv[1], argv[2] );
    break; case DIRECTORY:
    cp_dir(argv[1], argv[2]);
    break; case FILES:
    fprintf(stderr, "Can't copy a directory to a file\n");
    exit(EXIT_FAILURE);
    break; default:
    fprintf(stderr, "%s(%d): file type error\n", __FILE__, __LINE__);
    break;
    }
    } return 0;
    }
  2. copy.c

    #include "copy_file.h"
    
    FILE_ENUM check_file(char *var, struct stat *st)
    {
    if( stat(var, st) ) //if stat function error(renturn nonzero)
    {
    if( ENOENT == errno) //No such file or directory
    {
    return NOT_EXIST;
    }
    else
    {
    perror("stat");
    exit(EXIT_FAILURE);
    }
    } else // stat() ok, no error
    {
    //check file attr(dir or file)
    if( S_ISDIR(st->st_mode ))
    return DIRECTORY;
    else if( S_ISREG(st->st_mode) )
    return FILES;
    else
    {
    fprintf(stderr, "%s(%d):file type error", __FILE__ , __LINE__);
    exit(EXIT_FAILURE);
    }
    }
    } //----------------------------------------------------- int cp_file(char *src_var, char *dest_var, struct stat *st)
    {
    FILE *src = NULL;
    FILE *dest = NULL; if( S_ISREG(st->st_mode) ) //if dest is file
    {
    //1. open src and dest file
    if( NULL == (src = fopen(src_var, "r")) )
    {
    perror("fopen");
    exit(EXIT_FAILURE);
    } if( NULL == (dest = fopen(dest_var, "w+")) )
    {
    perror("fopen");
    exit(EXIT_FAILURE);
    } //2. copy the context from src to dest
    char buf[1024];
    int num; while(1)
    {
    // if at the end of file or an error occured
    if( 1024 != (num = fread(buf, 1,1024, src)))
    {
    if( !feof(src))
    {
    perror("fread");
    exit(EXIT_FAILURE);
    } else
    {
    fwrite(buf, 1, num, dest);
    fclose(dest); //3. close dest file
    break;
    }
    }
    fwrite(buf, 1, 1024, dest); } //3. close src file
    fclose(src);
    return 0;
    } if( S_ISDIR(st->st_mode) )
    {
    char buf[100]=""; //make the relative path to absolute path
    strncpy(buf, dest_var, sizeof(dest_var));
    strcat(buf, src_var); //if dest file doesn't exist, creat it first
    char cmd[100]="";
    sprintf(cmd, "touch %s",buf);
    system(cmd); struct stat new_dest_stat; if( stat(buf, &new_dest_stat))
    {
    perror("stat");
    exit(EXIT_FAILURE);
    } cp_file(src_var, buf, &new_dest_stat);
    } return 0;
    } //----------------------------------------------
    //if src file is a dir
    int cp_dir(char *src, char *dest)
    {
    DIR *dirp = NULL; //1. open the dir
    if( NULL == (dirp = opendir(src)) )
    {
    perror("opendir");
    exit(EXIT_FAILURE);
    } struct dirent *entp = NULL; //2. read the dir
    while( NULL != (entp = readdir(dirp))) //read the dir context
    {
    if( 0 == (strcmp(entp->d_name,"..")) || 0 == (strcmp(entp->d_name, ".")))
    {
    continue;
    } char src_buf[100] = "";
    char dest_buf[100] = ""; sprintf(src_buf, "%s/%s\0", src, entp->d_name);
    sprintf(dest_buf, "%s/%s\0", dest, entp->d_name); struct stat src_stat; if( stat(src_buf,&src_stat) )
    {
    perror("stat");
    exit(EXIT_FAILURE);
    } if( S_ISREG(src_stat.st_mode) )
    {
    cp_file(src_buf, dest_buf, &src_stat);
    } else if( S_ISDIR(src_stat.st_mode) )
    {
    if( -1 == mkdir(dest_buf, src_stat.st_mode) )
    {
    perror("mkdir");
    exit(EXIT_FAILURE);
    } cp_dir(src_buf, dest_buf); //if subdir, recursive call itself
    }
    } return 0;
    }
  3. copy.h

    #ifndef _COPY_H_
    #define _COPY_H_ #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <string.h>
    #include <dirent.h>
    #include <stdlib.h> typedef enum
    {
    NOT_EXIST=1,
    DIRECTORY,
    FILES
    }FILE_ENUM; extern FILE_ENUM check_file(char *var, struct stat *st); //检查文件类型 extern int cp_file(char *src_var, char *dest_var, struct stat *st); //copy文件 extern int cp_dir(char *src, char *dest); //copy目录 #endif

Linux 命令 "cp" 代码实现简介的更多相关文章

  1. linux 命令cp拷贝

    linux复制指定目录下的全部文件到另一个目录中复制指定目录下的全部文件到另一个目录中文件及目录的复制是经常要用到的.linux下进行复制的命令为cp.假设复制源目录 为 dir1 ,目标目录为dir ...

  2. Linux命令——cp、rm、mv、touch、file、dir

    cp copy 拷贝文件 拷贝过程不指定目标文件名 则目标文件名和源文件名一样 [root@WebServer ~]# cp /91xueit/teacher.txt 51cto/ 拷贝过程指定目标文 ...

  3. linux命令-cp/scp {拷贝}

    一 命令解释 名称:cp 使用权限:所有使用者 使用方式: cp [options] source dest cp [options] source... directory 命令参数: -a 尽可能 ...

  4. Linux命令-cp

    cp命令用于复制文件到目录 参数 -r 递归持续复制(用于目录) 参数 -p 保留原始文件属性 参数 -d 若对象为链接文件,保留该链接文件的属性 参数 -a 相当于以上三者之和(-pdr) [roo ...

  5. Linux 命令 - cp: 拷贝文件和目录

    命令格式 cp [OPTION]... [-T] SOURCE DEST cp [OPTION]... SOURCE... DIRECTORY cp [OPTION]... -t DIRECTORY ...

  6. linux命令--cp、tail、cd、mv、history、cd

    day1 cd命令 cd ../定位至上级目录 cd ./定位到当前目录 cd ~ 定位当前用户目录 cd / 定位系统根目录 cd - 返回进入此目录之前所在的目录 day2 mv命令: mv时,若 ...

  7. linux命令 cp 递归复制 带权限复制

    cp -r 递归复制源目录下所有文件及子目录 到 目标目录或文件 cp -p 把源文件或目录下的所具有的权限一同复制 到 目标目录或文件

  8. linux 命令cp -a的用法

    cp -a 保留原文件属性的前提下复制文件 cp -r dirname(源文件) destdi(目标文件) 复制目录后其文件属性会发生变化想要使得复制之后的目录和原目录完全一样包括文件权限,可以使用c ...

  9. 核心系统命令实战 第一章Linux命令行简介

    第一章Linux命令行简介 1.1 Linux命令行概述 1.1.1 Linux 命令行的开启和退出 开启:登陆账号密码进入系统 退出:exit/logout  快捷键:Ctrl+d 1.1.2 Li ...

随机推荐

  1. App主导现在 HTML5领衔未来

    HTML5能够让开发人员构建丰富的基于Web应用程序,使其能在任何设备中使用标准的Web浏览器.很多人认为HTML5将会让App过时.到底App还是HTML5会是谁赢得最后的胜利,在业界也有不少讨论, ...

  2. TFS中设置任务中的“计划开始时间”为可编辑状态

    问题现象 如果使用TFS系统的默认模板CMMI新建团队项目,你会发现在网页浏览器中,任务工作项的"计划开始日期"和"计划结束日期"的类型是普通字符,并且不能修改 ...

  3. BlangenOA项目总结

    1.使用EF,当返回的是IQueryable<T>类型,延迟加载. 2.增删改查 分页(页码,页大小,总记录数,是否升序)(两个lambda表达式,一个筛选规则,一个是排序规则(可以选择类 ...

  4. 在centos7升级jenkins

    找到jenkins的位置 使用下面的命令 ps -aux | grep jenkins enkins    5954  7.9 22.5 2695800 421088 ?      Ssl  20:5 ...

  5. SqlAlchemy操作(三)

    1.基于SQLALCHEMY建表 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Colu ...

  6. jzoj5888

    tj:暴力連邊會tle 我們發現所有邊的邊權最大值不超過100000,這意味著可以設計和邊權有關的算法,假設現在邊權不相同 枚舉一個現在的邊權i,代表gcd為i,設連的2個點權值為a1∗ia1*ia1 ...

  7. (进阶篇)PHP(thinkphp5框架)实现用户注册后邮箱验证,激活帐号

    本文将结合实例,讲解如何使用thinkphp5+Mysql完成注册帐号.发送激活邮件.验证激活帐号.处理URL链接过期的功能. 业务流程 1.用户提交注册信息. 2.写入数据库,此时帐号状态未激活. ...

  8. Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题

    King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...

  9. 正则表达式学习之grep,sed和awk

    正则表达式是用于描述字符排列和匹配模式的一种语法,它主要用于字符串的模式分割.匹配.查找以及替换操作. 描述一个正则表达式需要字符类.数量限定符.位置限定符.规定一些特殊语法表示字符类,数量限定符和位 ...

  10. iOS下载图片失败

    一.具体问题 开发的过程中,发现某个界面部分图片的显示出现了问题只显示占位图片,取出图片的url在浏览器却是能打开的,各种尝试甚至找同行的朋友帮忙在他们项目里展示都会存在问题,最终发现通过第三方框架S ...