zoukankan      html  css  js  c++  java
  • Linux 命令 "cp" 代码实现简介

    本blog主要是模仿Linux的cp命令的功能,未实现参数,只是基础功能部分。
    本文的主要目的在于练习 文件流目录流 中的函数的使用。

    主要功能包括两种:

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

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

    本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!
      ",__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]
      ", 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
      ", __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
      ");
                      exit(EXIT_FAILURE);
                      break;
                  
                  default:
                      fprintf(stderr, "%s(%d): file type error
      ", __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", src, entp->d_name);
              sprintf(dest_buf, "%s/%s", 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
  • 相关阅读:
    【C# 代码小技巧】巧用 linq select 实现遍历集合返回元素 index
    [转载] redis 学习
    Html5 Canvas斗地主游戏
    K-近邻算法(KNN)
    Sql 把Xml字符串转换成一张表
    Asp.Net Mvc4分页,扩展HtmlHelper类
    SQL 分割字符串
    http://q.cnblogs.com/q/54251/
    读强化学习论文之MADDPG
    【回归】记Paddle强化学习训练营
  • 原文地址:https://www.cnblogs.com/Jimmy1988/p/7509932.html
Copyright © 2011-2022 走看看