歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux C 實現mycp 可以顯示文件拷貝進度

在Linux系統裡面用到 cp命令復制不能顯示文件拷貝的進度,也不能計算還有多長時間文件可以 拷貝結束,現在寫一個程序可以顯示文件拷貝的進度。

思路:當前目錄下面有一個1G大小的bigfile文件

當我在命令行下面輸入ls -lh bigfile,我會得到這個文件的詳細信息,當然也可以看到文件的大小。

www.linuxidc.com@linuxidc~$ ls -lh bigfile
-rw-rw-r-- 1 nii nii 1000M  7月 13 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下執行結果為:

www.linuxidc.com@linuxidc:~/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 秒

Copyright © Linux教程網 All Rights Reserved