有时候要对整个目录做备份,修改cp1.c使得当两个参数都是目录时,把第一个目录中的所有文件复制到第二个目录中,文件名不变。那么该如何实现?
  我们先来看看cp1.c的实现方式,它从一个文件中读取数据然后写到另一个文件中,通过系统调用open(或者creat)、read、wirte和close来完成。从上面我们看出,cp1.c只是针对于一个文件进行的复制操作,而现在我们需要完成对整个目录的备份。参数由一个单独的文件(file)变成一个目录(directory),所以我们首先想到的就是要先进入到这个目录下,然后对该目录下的文件依次进行cp操作,那么这就涉及到了目录的操作,而我们在第三章ls命令的实现过程中,用到的就是对目录的操作,涉及到的系统调用包含有opendir、readdir和closedir。所以现在我们需要把两者用到的技术联系起来,以便完成对目录的备份工作。
  具体实现:
    1、命令行参数
      int argc、char *argv[]
    2、cp源、目的的类型判断
      src为dir,dst也必须是dir
      src为file,dst可以是anything
    3、目录操作
      opendir进入src目录下;
      while{
        readdir获得当前目录下的文件(或目录),递归判断是否还是目录,如果是继续深入;
        srcpath、dstpath获取,调用cp完成复制;
      }
      closedir完成目录复制
    4、cp实现
      in=open(src);out=creat(dst)
      while{
        read(in);
        write(out);
      }
      close(in);close(out)

具体的代码如下:

 /** cp1.c
* version 1 of cp - uses read and write with tunable buffer size
*
* usage: cp1 src dest
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> #define BUFFERSIZE 4096
#define COPYMODE 0644 void oops(char *, char *); main(int ac, char *av[])
{
int in_fd, out_fd, n_chars;
char buf[BUFFERSIZE];
/* check args */
if ( ac != ){
fprintf( stderr, "usage: %s source destination\n", *av);
exit();
}
/* open files */ if ( (in_fd=open(av[], O_RDONLY)) == - )
oops("Cannot open ", av[]); if ( (out_fd=creat( av[], COPYMODE)) == - )
oops( "Cannot creat", av[]); /* copy files */ while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > )
if ( write( out_fd, buf, n_chars ) != n_chars )
oops("Write error to ", av[]);
if ( n_chars == - )
oops("Read error from ", av[]); /* close files */ if ( close(in_fd) == - || close(out_fd) == - )
oops("Error closing files","");
} void oops(char *s1, char *s2)
{
fprintf(stderr,"Error: %s ", s1);
perror(s2);
exit();
}

 改进(添加目录判断)之后的具体实现:

 /** cp2.c
** ------------------------------------------------------------
cp2.c is a
revised version of cp1.c that can copy an entire directory
file by file to a second directory. It also supports some
of the features required by earlier exercises. ** ------------------------------------------------------------
**
**
* A version of cp1.c that works if src or dest name directories
* (but not if src is a directory and dest is not)
*
* usage: cp1 src dest
* If dest names a directory, then copy src to dest/src
* If src names a directory, then copy all files in src to dest
* If src is a directory and dest is NOT a directory, quit
* Note: if src has a leading path, then only use last component
*
* build: cc sol03.14.c -o sol03.14
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <dirent.h> #define BUFFERSIZE 4096
/*
* note: the real copy takes the mode of the copy from
* the mode of the source.
*/
#define COPYMODE 0644 void oops(char *, char *);
void *emalloc(size_t); int
main(int ac, char *av[])
{
if ( ac != ){
fprintf( stderr, "usage: %s source destination\n", *av);
exit();
} /*
* if source is a dir, then the dest has to be, too
*/ if ( isadir(av[]) ){
if ( isadir(av[]) )
copydir(av[], av[]);
else {
fprintf(stderr,"cp1: %s is not a directory\n", av[]);
exit();
}
}
/*
* if source is not a dir, then the dest can be anything
*/
else
do_copy( av[], av[] );
return ;
} /*
* copydir()
* loops through all files in srcdir, copying each to destdir
* uses do_copy but builds the paths here
* Note: this function skips subdirectories of srcdir
*/
copydir(char *srcdir, char *destdir)
{
char *srcpath, *destpath;
DIR *dir_ptr;
struct dirent *direntp; srcpath = (char *) emalloc(strlen(srcdir)++MAXNAMLEN+);
destpath = (char *) emalloc(strlen(destdir)++MAXNAMLEN+);
if ( (dir_ptr = opendir(srcdir)) == NULL )
oops("Cannot open directory", srcdir); /*
* loop through all items in src dir
* Do not copy directories, and report that so user
* realizes not all the items are copied.
*/
while( ( direntp = readdir(dir_ptr)) != NULL )
{
sprintf(srcpath,"%s/%s", srcdir, direntp->d_name);
if ( isadir(srcpath) ){
if ( strcmp(direntp->d_name,".") != &&
strcmp(direntp->d_name,"..") != )
printf("skipping directory %s\n", srcpath);
continue;
}
sprintf(destpath, "%s/%s", destdir, direntp->d_name);
do_copy( srcpath, destpath );
}
closedir(dir_ptr);
free(srcpath);
free(destpath);
} /*
* copies a file from src to dest
* If dest is a directory, then do_copy() copies to
* a file in dest with the name taken from the filename for
* src
*/
do_copy(char *src, char *dest)
{
int in_fd, out_fd, n_chars;
char buf[BUFFERSIZE];
char *destfilename;
char *make_destfilename(char*,char*); destfilename = make_destfilename(src, dest); /*
* open files
*/ if ( (in_fd=open(src, O_RDONLY)) == - )
oops("Cannot open ", src); if ( (out_fd=creat( destfilename, COPYMODE)) == - )
oops( "Cannot creat", destfilename); /*
* copy files
*/ while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > )
if ( write( out_fd, buf, n_chars ) != n_chars )
oops("Write error to ", destfilename);
if ( n_chars == - )
oops("Read error from ", src); /*
* close files
*/ if ( close(in_fd) == - || close(out_fd) == - )
oops("Error closing files","");
} void oops(char *s1, char *s2)
{
fprintf(stderr,"Error: %s ", s1);
perror(s2);
exit();
} /*
* if dest is a directory, then combine src and dest
* (see header to this program)
*/ char *
make_destfilename(char *src, char *dest)
{
struct stat info;
char *srcfilename;
char *rv; if ( stat(dest, &info) == - ) /* let someone else handle this */
return dest; if ( ! S_ISDIR(info.st_mode) ) /* ok to copy to other types */
return dest; /* find last component of source name */
if ( (srcfilename = strrchr(src, '/')) != NULL )
srcfilename++;
else
srcfilename = src; /* use that to construct target name */
rv = emalloc(strlen(srcfilename) + strlen(dest) + );
sprintf(rv, "%s/%s", dest, srcfilename); return rv;
} void *
emalloc(size_t n)
{
void *rv = malloc(n);
if ( rv == NULL )
oops("Out of memory","");
return rv;
}
/*
* boolean: tells if arg names a directory
*/
isadir(char *str)
{
struct stat info; return ( stat(str,&info) != - && S_ISDIR(info.st_mode) );
}

编写自己的cp命令的更多相关文章

  1. cp/tar/用c语言编写程序 实现cp命令的效果

    1.cp (拷贝) 已存在文件路径  要拷贝的文件路径 实现cp命令的代码如下: #include <stdio.h> //因为要在命令中得到两个路径,所以要用到main函数的两个参数 i ...

  2. 关于cp命令的编写

    关于cp命令的编写 娄老师在课上详细的讲了命令who的编写过程~对此,我很有启发!于是想亲自动手试试~ 有什么不足的地方请大家提出来! Learning by doing ~ 做中学,真的只有自己动手 ...

  3. cp命令的编写——浅谈系统调用

    摘要:linux中cp命令的实现,通过这个程序,我们需要了解系统调用耗费时间的方面,同时学会系统调用的错误处理机制. 本文来源:http://blog.csdn.net/trochiluses/art ...

  4. linux系统编程:自己动手写一个cp命令

    cp命令的基本用法: cp 源文件 目标文件 如果目标文件不存在 就创建, 如果存在就覆盖 实现一个cp命令其实就是读写文件的操作: 对于源文件: 把内容全部读取到缓存中,用到的函数read 对于目标 ...

  5. 每天一个Linux命令(10)cp命令

    cp命令用来将一个或多个源文件或者目录复制到指定的目的文件或目录.它可以将单个源文件复制成一个指定文件名的具体的文件或一个已经存在的目录下.cp命令还支持同时复制多个文件,当一次复制多个文件时,目标文 ...

  6. Linux命令学习总结:cp命令

    命令简介: cp命令用来复制文件或目录.指令英文原义:copy 指令所在路径:/bin/cp 命令语法: Usage: cp [OPTION]... [-T] SOURCE DEST or: cp [ ...

  7. 【初级】linux cp 命令详解及使用方法实战

    cp:复制文件或者目录 前言: cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不 ...

  8. linux命令(8):cp 命令

    cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...

  9. Linux cp命令使用说明

    Linux cp命令使用说明 --功能说明:复制目录或文件 --命令格式:cp  [参数]  <文件或目录>  <文件或目录> --常用参数: -R 复制目录 -i 覆盖文件之 ...

随机推荐

  1. transition状态下Mecanim动画的跳转

    来自: http://blog.csdn.net/o_oxo_o/article/details/21325901 Unity中Mecanim里面动画状态的变化,是通过设置参数(Parameter)或 ...

  2. CentOS系统使用yum安装配置MariaDB数据库

    http://www.server110.com/mariadb/201310/2670.html 1.在 /etc/yum.repos.d/ 下建立 MariaDB.repo,内容如下:[azure ...

  3. Python——描述符(descriptor)解密

    本文由 极客范 - 慕容老匹夫 翻译自 Chris Beaumont.欢迎加入极客翻译小组,同我们一道翻译与分享.转载请参见文章末尾处的要求. Python中包含了许多内建的语言特性,它们使得代码简洁 ...

  4. C# NPOI操作Excel(下)

    根据自己项目需求编写,仅供参考 个人建议:使用Excel模板进行导出操作.尽量避免自己生成Excel(既繁琐又容易出BUG).大多情况下导出Excel都是固定格式,使用模板导出会方便很多. publi ...

  5. 基于Python3 + OpenCV3.3.1的远程监控程序

    基于Python3 + OpenCV3.3.1的远程监控程序 一.环境配置 OpenCV是一个基于(开源)发行的跨平台计算机视觉库,利用OpenCV能够实现视频图像的捕获. 关于python3中Ope ...

  6. mysql bin-log三种模式

    MySQL的bin-log日志备份有三种模式,分别是:ROW.Statement.Mixed 一.Row 日志会记录成每一行数据被修改成的形式,然后再slave端再对相同的数据进行修改,只记录要修改的 ...

  7. Painting Fence

    Painting Fence Time Limit:1000MS     Memory Limit:524288KB     64bit IO Format:%I64d & %I64u Sub ...

  8. eclipse 建立maven项目 显示红叉的解决方法

    1.建立好之后就会发现项目有红叉. 这时发现查查在main处,打开项目>属性>Java Build Path>source,发现里边有红叉(如下图),这是由于我们的src/main下 ...

  9. IE浏览器上传图片预览兼容(IE 7 8 9 10 11)

    $("#file_upload").change(function () { var $file = $(this); ]; var windowURL = window.URL ...

  10. 在python中Flask配置服务

    from flask import Flask, request from data_util import UtilsLTPTranslate import json model = UtilsLT ...