编写自己的cp命令
有时候要对整个目录做备份,修改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命令的更多相关文章
- cp/tar/用c语言编写程序 实现cp命令的效果
1.cp (拷贝) 已存在文件路径 要拷贝的文件路径 实现cp命令的代码如下: #include <stdio.h> //因为要在命令中得到两个路径,所以要用到main函数的两个参数 i ...
- 关于cp命令的编写
关于cp命令的编写 娄老师在课上详细的讲了命令who的编写过程~对此,我很有启发!于是想亲自动手试试~ 有什么不足的地方请大家提出来! Learning by doing ~ 做中学,真的只有自己动手 ...
- cp命令的编写——浅谈系统调用
摘要:linux中cp命令的实现,通过这个程序,我们需要了解系统调用耗费时间的方面,同时学会系统调用的错误处理机制. 本文来源:http://blog.csdn.net/trochiluses/art ...
- linux系统编程:自己动手写一个cp命令
cp命令的基本用法: cp 源文件 目标文件 如果目标文件不存在 就创建, 如果存在就覆盖 实现一个cp命令其实就是读写文件的操作: 对于源文件: 把内容全部读取到缓存中,用到的函数read 对于目标 ...
- 每天一个Linux命令(10)cp命令
cp命令用来将一个或多个源文件或者目录复制到指定的目的文件或目录.它可以将单个源文件复制成一个指定文件名的具体的文件或一个已经存在的目录下.cp命令还支持同时复制多个文件,当一次复制多个文件时,目标文 ...
- Linux命令学习总结:cp命令
命令简介: cp命令用来复制文件或目录.指令英文原义:copy 指令所在路径:/bin/cp 命令语法: Usage: cp [OPTION]... [-T] SOURCE DEST or: cp [ ...
- 【初级】linux cp 命令详解及使用方法实战
cp:复制文件或者目录 前言: cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不 ...
- linux命令(8):cp 命令
cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...
- Linux cp命令使用说明
Linux cp命令使用说明 --功能说明:复制目录或文件 --命令格式:cp [参数] <文件或目录> <文件或目录> --常用参数: -R 复制目录 -i 覆盖文件之 ...
随机推荐
- java中short、int、long、float、double取值范围
一.分析基本数据类型的特点,最大值和最小值.1.基本类型:int 二进制位数:32包装类:java.lang.Integer最小值:Integer.MIN_VALUE= -2147483648 (-2 ...
- PuTTY连接Linuxserver常常断线解决方式
PuTTY在远程连接server之后.常常会断线提示"Software caused connection abort",并且常常在非常短的时间内就失去连接. 解决方式例如以下: ...
- cocos2d-x 重力感应 加速器的使用
CSDN开通已有两三年,今天作为一名刚入行的菜鸟写下自己的第一篇Blog. 刚好项目中须要用到重力感应,google下发现重力感应的使用很easy. 例如以下: 第一步: 在当前层开启重力感应.函数: ...
- LightOJ 1070 - Algebraic Problem 矩阵高速幂
题链:http://lightoj.com/volume_showproblem.php?problem=1070 1070 - Algebraic Problem PDF (English) Sta ...
- C# 通过 AppDomain 应用程序域实现程序集动态卸载或加载
AppDomain 表示应用程序域,它是一个应用程序在其中执行的独立环境.每个应用程序只有一个主应用程序域,但是一个应用程序可以创建多个子应用程序域. 因此可以通过 AppDomain 创建新的应用程 ...
- 83. Remove Duplicates from Sorted List【easy】
83. Remove Duplicates from Sorted List[easy] Given a sorted linked list, delete all duplicates such ...
- MAJOR-MINOR-MKDEV
标记一下,容易忘,以免每次查代码. ./include/linux/types.h:21:typedef __u32 __kernel_dev_t; ./include/linux/types.h:2 ...
- NGINX扩展
https://github.com/cuber/ngx_http_google_filter_module
- ccentos 7下安装php5.6并使用nginx + php-fpm部署多个不同端口网站
作为一个的勤杂工,近期因公司内部信息化的需求,给新进员工提供基础的知识培训和介绍,也为了给公司内部建立一个沟通交流的平台,百度找了开源的百科系统HDwiki和开源的问答系统Tipask问答系统,蛋痛的 ...
- java中的static方法和实例方法区别
1.static方法是大家共享的资源,放在内存堆中,比如村里的河水,每个人都可以取,而且不管你创建多少个实例,该方法在内存中只有一个,节省内存空间, 而且访问速度也是比较快的. 2.实例方法就不同,它 ...