本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. RandomForest in Spark MLLib

    决策树类模型 ml中的classification和regression主要基于以下几类: classification:决策树及其相关的集成算法,Logistics回归,多层感知模型: regres ...

  2. efcore操作mysql,出现System.InvalidOperationException:“No coercion operator is defined between types 'System.Int16' and 'System.Boolean'.”

    这个恶心的问题,只需要把EF的依赖换成 Pomelo.EntityFrameworkCore.MySql 库即可解决

  3. 逆变(contravariant)与协变(covariant)

    逆变(contravariant)与协变(covariant)是C#4新增的概念,许多书籍和博客都有讲解,我觉得都没有把它们讲清楚,搞明白了它们,可以更准确地去定义泛型委托和接口,这里我尝试画图详细解 ...

  4. JAVA 定时器时间格式

    格式: [秒] [分] [小时] [日] [月] [周] [年] 通配符说明: \*:表示所有值.例如:在分的字段上设置"\*",表示每一分钟都会触发. ?:表示不指定值.使用的场 ...

  5. HTTP协议、HTTP协议原理分析

    百度百科中说明: 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为 ...

  6. python 简单搭建阻塞式单进程,多进程,多线程服务

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 我们可以通过这样子的方式去理解apache的工作原理 1 单进程TCP服 ...

  7. 内核漏洞学习—熟悉HEVD

    一直以来内核漏洞安全给很多人的印象就是:难,枯燥.但是内核安全是否掌握是衡量一个系统安全工程师水平的标准之一,也是安全从业人员都应该掌握的基本功.本文通过详细的实例带领读者走进内核安全的大门.难度系数 ...

  8. python实战——网络爬虫

    学习网络爬虫的目的: 1,可以私人定制一个搜索引擎,可以深层次的了解搜索引擎的工作原理. 2,大数据时代,要进行数据分析,首先要有数据源,学习爬虫,可以让我们获取更多的数据. 3,从业人员可以可好的利 ...

  9. 手把手教你如何安装和使用Karma-Jasmine

    注意:本文中出现的资料链接.karma的插件安装等,均可能需要翻$墙后才能正确执行. Jasmine是一个Javascript的测试工具,在Karma上运行Jasmine可完成Javascript的自 ...

  10. JS实现一个基于对象的链表

    JS实现一个基于对象的链表 /*JS实现一个基于对象的链表*/ function Node(element){ this.element = element;//节点存储的元素 this.next = ...