Linux C 实现mycp 可以显示文件拷贝进度

在Linux系统里面用到 cp命令复制不能显示文件拷贝的进度,也不能计算还有多长时间文件可以 拷贝结束,现在写一个程序可以显示文件拷贝的进度。

思路:当前目录下面有一个1G大小的bigfile文件

当我在命令行下面输入ls -lh bigfile,我会得到这个文件的详细信息,当然也可以看到文件的大小。

nii@ww:~$ ls -lh bigfile 
-rw-rw-r-- 1 nii nii 1000M  713 19:41 bigfile

我们可以用popen函数,把执行之后的结果”-rw-rw-r– 1 nii nii 1000M 7月 13 19:41 bigfil”这串字符串接收下来,我们可以提取出来表示文件大小的那段字符串,比如这个我们可以提取”1000”在用atoi函数,把字符串转换为int型数值1000(不了解popen函数和atoi函数的请自行学习),就可以获得文件大小。
例如我的文件名字叫mycp.c,我执行gcc -o mycp mycp.c生成一个mycp的可执行文件。

接下来我在命令行上输入./mycp bigfile destbigfile把当前目录下面的bigfile文件拷贝为destbigfile,这时我产生一个子进程,子进程负责调用系统的cp命令拷贝,父进程每隔一秒钟,去获取destbigfile、bigfile 文件的大小,就可以知道拷贝的进度,当然也可以获得拷贝的时间,就可以计算出来离拷贝结束还有多长时间。

下面是代码的实现:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

/** 得到文件的详细信息 */
int getFileMsg(char* pchCmd,char *pchMsg);

int main(int argc,char* argv[])
{

    char szSrcFileMsg[150] = {0};
    char szSrcFileSizeMsg[10] = {0};
    int  nSrcFileSize = 0;

    char szSDestFileMsg[150] = {0};
    char szDestFileSizeMsg[10] = {0};
    int  nDestFileSize = 0;

    int pid = 0;
    /** shell执行的命令 ,在创建文件的时候使用*/
    char szExcueCommand[150] = {0};
    float fRate = 0;

    int nUsedTime = 0;
    float nLastTime = 0;

    /** 入参必须是三个 */
    if (1 == argc)
    {
        printf("please input the src and des file\n");
        return -1;
    }

    /** 产生子进程 */
    pid = fork();

    /** 如果是子进程,负责执行复制命令 */
    if (0 == pid)
    {
        sprintf(szExcueCommand,"%s %s %s","cp",argv[1],argv[2]);
        printf("%s\n",szExcueCommand);
        system(szExcueCommand);
        return 0;
    }
    /** 父进程负责把正在复制的原文件和复制的目标文件的大小计算出来,就可以知道复制的进度,计算频率为1秒一次 */
    else
    {
        /** 获得原文件的大小 */
        if (-1 == getFileMsg(argv[1],szSrcFileMsg))
        {
            printf("get sorce file message failed \n");
            return -1;
        }
        /** 把原文件大小的信息取出来 */
        strncpy(szSrcFileSizeMsg,szSrcFileMsg+21,4);
        szSrcFileSizeMsg[5] = '\0';
        nSrcFileSize = atoi(szSrcFileSizeMsg);

        while(1)
        {
            sleep(1);

            nUsedTime ++;

            /** 获得目标文件的大小 */
            if (-1 == getFileMsg(argv[2],szSDestFileMsg))
            {
                printf("get dest file message failed \n");
                return -1;
            }

            /** 把原文件大小的信息取出来 */
            strncpy(szDestFileSizeMsg,szSDestFileMsg+21,4);
            szDestFileSizeMsg[5] = '\0';
            nDestFileSize = atoi(szDestFileSizeMsg);
            /*** 计算复制的进度 */
            fRate = (nDestFileSize * 100) / nSrcFileSize ;

            /** 计算剩下的时间 */
            nLastTime = ((100 - fRate) * nUsedTime) / fRate;

            /** 打印进度条 */
            printf("已复制 %.2f %%   还需要  %.1f  秒\n",fRate,nLastTime);
            /** 复制完成之后,退出循环 */
            if (nSrcFileSize == nDestFileSize)
            {
                printf("复制完成,耗时 %d 秒\n",nUsedTime);
                break;
            }   
        }

    }   

    return 0;
}
/** 得到文件的详细信息 */
int getFileMsg(char* pchCmd,char *pchMsg)
{
    FILE *fstream=NULL;  
    char szBuff[BUFSIZ] = {0};
    char szExcueCommand[150] = {"ls -lh"};

    sprintf(szExcueCommand,"%s %s",szExcueCommand,pchCmd);

    if (NULL==(fstream=popen(szExcueCommand,"r")))    
    {   
        perror("execute command failed: ");
        return -1;    
    }   
    /** 得到命令的结果 */
    if (NULL == fgets(szBuff, sizeof(szBuff), fstream))   
    {   
        pclose(fstream);  
        return -1;  
    }  

    pclose(fstream); 

    strcpy(pchMsg,szBuff);
    return 0;
}

Linux下执行结果为:

nii@ww:~/advance_code/homework/signal$ ./mycp bigfile destbigfile
cp bigfile destbigfile
已复制 3.00 %   还需要  32.3  秒
已复制 5.00 %   还需要  38.0  秒
已复制 8.00 %   还需要  34.5  秒
已复制 10.00 %   还需要  36.0  秒
已复制 12.00 %   还需要  36.7  秒
已复制 13.00 %   还需要  40.2  秒
已复制 14.00 %   还需要  43.0  秒
已复制 17.00 %   还需要  39.1  秒
已复制 20.00 %   还需要  36.0  秒
已复制 21.00 %   还需要  37.6  秒
已复制 24.00 %   还需要  34.8  秒
已复制 24.00 %   还需要  38.0  秒
已复制 27.00 %   还需要  35.1  秒
已复制 32.00 %   还需要  29.8  秒
已复制 33.00 %   还需要  30.5  秒
已复制 35.00 %   还需要  29.7  秒
已复制 38.00 %   还需要  27.7  秒
已复制 41.00 %   还需要  25.9  秒
已复制 42.00 %   还需要  26.2  秒
已复制 43.00 %   还需要  26.5  秒
已复制 44.00 %   还需要  26.7  秒
已复制 48.00 %   还需要  23.8  秒
已复制 50.00 %   还需要  23.0  秒
已复制 52.00 %   还需要  22.2  秒
已复制 53.00 %   还需要  22.2  秒
已复制 53.00 %   还需要  23.1  秒
已复制 57.00 %   还需要  20.4  秒
已复制 59.00 %   还需要  19.5  秒
已复制 61.00 %   还需要  18.5  秒
已复制 63.00 %   还需要  17.6  秒
已复制 63.00 %   还需要  18.2  秒
已复制 66.00 %   还需要  16.5  秒
已复制 69.00 %   还需要  14.8  秒
已复制 70.00 %   还需要  14.6  秒
已复制 72.00 %   还需要  13.6  秒
已复制 73.00 %   还需要  13.3  秒
已复制 75.00 %   还需要  12.3  秒
已复制 78.00 %   还需要  10.7  秒
已复制 79.00 %   还需要  10.4  秒
已复制 82.00 %   还需要  8.8  秒
已复制 83.00 %   还需要  8.4  秒
已复制 84.00 %   还需要  8.0  秒
已复制 87.00 %   还需要  6.4  秒
已复制 90.00 %   还需要  4.9  秒
已复制 91.00 %   还需要  4.5  秒
已复制 93.00 %   还需要  3.5  秒
已复制 93.00 %   还需要  3.5  秒
已复制 96.00 %   还需要  2.0  秒
已复制 99.00 %   还需要  0.5  秒
已复制 100.00 %   还需要  0.0  秒
复制完成,耗时 50
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dmfrm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值