编写自己的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 覆盖文件之 ...
随机推荐
- 无password身份验证:安全、简单且部署高速
Passwordless authentication: Secure, simple, and fast to deploy [编者按]本文作者为 Florian Heinemann 与 Rober ...
- HDU 4632 Palindrome subsequence(区间dp)
Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65535 K (Java/ ...
- C#运用反射调用其他程序集中的代码
加载程序集 AssMedicalAdvice = Assembly.LoadFrom(Path.Combine(Environment.CurrentDirectory, "Inscript ...
- Sonatype Nexus
Maven 常用的仓库管理http://zh.wikipedia.org/wiki/Apache_Maven
- SDUTOJ 2712 5-2 派生类的构造函数
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUl9NaXNheWE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...
- c++ 类内部 使用 new delete
低级错误: /** * @clusterNums 默认为5 分类数目 * @xyVector 处理后点云数据 x y顺序存储 */ int GMM::runGMM(int clusterNums, c ...
- 转:[windows]DOS批处理添加任务计划
自动创建每周运行一次的计划任务 创建计划任务可用at,schtasks命令,schtasks提供了很多参数 命令schtasks SCHTASKS /Create [/S system [/U use ...
- mysql 函数substring_index() 截取字符串
函数: 1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例:select left(content,200) as abstract from my ...
- Atitit.创建快捷方式 windows快捷方式的原理
Atitit.创建快捷方式 windows快捷方式的原理 1. Windows中有2种快捷方式的文件:1 2. Jshortcut2 2.1. 提示新不上jshortcut.dll2 2.2. 使用w ...
- [容器]gcr.io镜像下载
下载gcr.io的镜像hosts文件 把下面两行加入到/etc/hosts中. 更多在这里http://wst.so/files/hosts 61.91.161.217 gcr.io 61.91.1 ...