Linux下自己实现cp命令

在Linux环境下,拷贝文件常用指令是cp,例如cp a.c b.c 就是将a.c的文件拷贝成名叫b.c的文件,那么cp 命令是怎么实现的呢,在此之前,先补充一个知识点。

带参数的main函数

在以往的编程中,我们的main函数一般写成以下形式:

                        int main()

                或        

                        int main(void)

括号中是空的或者有“void”,表示main函数没有参数,调用main函数时不用给出实参。

但是有些情况下,main函数可以有参数,即int main(int argc,char *argv[ ])

其中argc和argv就是main函数的形参,他们是程序的“命令行参数”,其中argc(arguement count的缩写,表示参数个数),argv(arguement vector的缩写,表示参数向量),它是一个指针数组,数组的每个元素都是指针,指向命令行中的字符首地址。第二个参数char *argv[ ]也可替换成char **argv,它是一个指向指针的指针,同样能达到相同的效果。

注意:在使用带参数的main函数时,第一个形参必须是int型,用来接收形参个数,第二个参数必须是字符指针数组,用来接收从操作系统命令行传来字符的地址。

从上图中可以看出,cp指令使用时,首先给出cp命令,然后将源文件a.c复制成目标文件b.c,因此一共有3个参数,即argc的值为3。argv里面共有三个地址,argv[0]指向cp,argv[1]指向a.c地址,argv[2]指向b.c地址。

#include<stdio.h>
int main(int argc,char **argv)
{
        printf("total parameters is :%d\n",argc);
        printf("No.1 parameter is %s\n",argv[0]);
        printf("No.2 parameter is %s\n",argv[1]);
        printf("No.3 parameter is %s\n",argv[2]);
        return 0;
}

在以上测试程序中,我们使用了带参数的main函数,分别验证其每个参数。

若采用以往的方式运行此段代码可以看到,当我们只给出./a.out一个参数指令时,argc的值为参数个数1,argv[0]也是我们的第一个命令行参数。

若我们给出完整的参数指令,就可以看到argc参数个数为3,第一个命令行参数argv[0]指向./a.out,第二个命令行参数argv[1]指向src.c,第三个命令行参数argv[2]指向des.c

cp命令的实现:

有以上的铺垫以后,我们先来分析以下文件是如何从源文件复制到目标文件的。其基本原理也是基于文件操作的相关指令,大致步骤如下:

1.打开被复制的源文件src.c

2.读取源文件src.c中的内容到读取缓冲器readBuf中

3.打开或者创建一个目标文件src.c,该文件是用于将复制的内容写入的地方

4.将读取缓冲器readBuf中的内容写入到目标文件src.c中

5.关闭源文件和目标文件,防止文件受损

在以上步骤中,相关的文件操作包括文件的打开open,文件的读取read,文件的写入write,文件的关闭close。

基于以上原理,便可用程序表述出来如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include<string.h>
int main(int argc,char **argv)
{
        int fdSrc;
        int fdDes;

        char *readBuf=NULL;
        if(argc!=3){
                printf("param error\n");
                exit(-1);
        }
        fdSrc=open(argv[1],O_RDWR);

        int size=lseek(fdSrc,0,SEEK_END);
        readBuf=(char *)malloc(sizeof(char)*size+8);
        lseek(fdSrc,0,SEEK_SET);
        int n_read=read(fdSrc,readBuf,size);

        fdDes=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);

        int n_write=write(fdDes,readBuf,strlen(readBuf));

        close(fdSrc);
        close(fdDes);

        return 0;
}

代码分析:在以上代码中,我们定义了两个文件描述符,分别是fdSrc源文件文件描述符,fdDes目标文件描述符。

1.首先判断用户给的参数个数是否是3个,若参数个数不对,则直接退出程序。

2.满足条件后,以可读可写的方式打开argv[1]指向的源文件Src.c,并获取源文件的文件描述符。

3.打开以后,读取文件描述符为fdSrc的源文件,将读取到的size大小的内容存放到读取缓冲器readBuf中,其中size大小可采用lseek的返回值来获取,readBuf存储空间的大小也由size的大小来决定。(注意:在读取以后光标移动到了文件末尾,再次读取时会从末尾开始造成读取为空,因此用lseek函数及时将光标移到文件头开始的地方)

4.读取源文件中的内容以后,打开目标文件,其中argv[2]指向文件描述符为fdDes的目标文件,若目标文件不存在则执行O_CREAT创建目标文件,若目标文件中在之前已有内容存放,则执行O_TRUNC去打开文件,并将其长度截短为0。

5.打开或创建目标文件以后,将我们从源文件读取并缓存到读取缓冲器readBuf中的内容写入到目标文件中。

6.关闭源文件和目标文件。

 在gcc编译时将生成的执行文件命名为mycp

在执行时,共有三个参数,argv[0]为./mycp参数指令,argv[1]指向源文件demo13.c,即被复制的文件,argv[2]指向目标文件new.c,即被粘贴内容的文件。在运行后便可看到新生成的new.c文件,该文件内容是复制demo13.c的内容,这样我们自己的mycp复制指令就完成了。 

  • 10
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值