1. 程式人生 > >Linux+Qt 下 tar 命令在GUI下執行,過程過程和結果資訊捕捉

Linux+Qt 下 tar 命令在GUI下執行,過程過程和結果資訊捕捉

#!/bin/sh

ls -Ral | grep -E "^(\-|d).*$" | grep -vE ".* (\.\.|\.)$" | wc -l

需求:Linux下使用GUI(qt)執行 tar 命令。需要顯示其過程和執行結果
設計:最初思路是想通過類似pv這樣的命令實時輸出執行比例和使用popen()函式監視執行結果。嘗試很久無果,主要是pv或類似pv的命令都不要用(或許我沒找到)。無意間關注到了ubuntu 檔案管理器(nautilus)壓縮與解壓縮的GUI顯示過程,從中得到了靈感。設計如下:
打包設計:
1,遞迴要打包的檔案和/或資料夾,獲取檔案和資料夾總數量:X1。
2,使用popen()函式執行 tar 打包檔案和/或資料夾命令,打包命令加上v(輸出打包資訊)引數。
3,fgets迴圈讀取popen() fork() 的子程序 標準輸出(stdout) 並記錄行數:X2。
4,使用 X2 除以 X1 得出 tar 命令執行進度百分比。
5,將進度與步驟3中得到的 tar 輸出資訊(檔名) 顯示到GUI中。
6,待命令操作完成時使用 pclose()得到 tar 執行結果(最終是否成功)並顯示。
注:如果 tar 執行遇到錯誤 plcose() 可以捕捉到,但是卻無法得到 tar 輸出的錯誤資訊,因為錯誤資訊是輸出到 stderr 中的。所以如果想要得到stderr中的異常資訊,必須重寫 popen() 和 pclose()。後面我會貼出 popen() 和 pclose() 原始碼。會用 fork(),dup2() 與 pipi() 的 可以自行修改。

解包設計:
與打包設計類似,不同點在於步驟1的獲取檔案/資料夾數量上

部分實現:
打包:
步驟1:遞迴獲取檔案和資料夾數量命令實現
命令:ls 資料夾 -Ra | grep -vE "^.*:$|^$|^\.\.$|^\.$" | wc -l
命令說明:使用 ls 命令加 R(遞迴子目錄)a(顯示所有檔案)獲取所有檔案和目錄。使用 grep 命令加v(不顯示匹配行)E(正則支援或)過濾掉 ls 命令的多餘輸出 和 “.” 和 “..” 資料夾。使用 wc -l 得到 總行數

步驟2:打包命令實現
命令實現:tar -zcvf 檔名.tar.gz 資料夾
命令說明:特別注意 v(輸出打包過程)引數。需要注意的是 步驟1單次 ls 得到的檔案/資料夾數量總是比步驟2的單個打包物件的數量少1。原因是因為 tar 命令輸出了當前打包路徑或檔案。而 ls 則不是。注意:如果同時打包 N 個檔案/資料夾 則 步驟2的數量比步驟1的數量多 N 。強迫症可以自己找平

解包:
步驟1:獲取解壓包檔案數量
命令實現:tar -tzf 檔名.tar.gz | wc -l
命令說明:tar 的 t 引數是隻輸出檔案資訊,並不解壓。wc -l 統計輸出行數(也就是檔案個數)

步驟2:解包
命令實現:tar -zxvf 檔名.tar.gz
命令說明: 注意加 v 引數

解包說明:我的實驗物件是 linux核心原始碼包(linux-3.14.17.tar.gz),一共有48890個檔案。由於裡面沒有大檔案。所以步驟1與步驟2的時間幾乎差不多。換句話說如果解包僅執行步驟2,耗時會省去一半。但是我看到Ubuntu解壓縮這個包時候也是如此。所以我不建議省去步驟1,或許解壓縮多個大檔案打包的壓縮包會有意義。解包步驟1過程也可能時間較長,因此注意執行解包步驟1時候進度條應該做loading顯示

#include <errno.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>

static int *pids;

FILE *
popen(program, type)
    char *program;
    register char *type;
{
    register FILE *iop;
    int pdes[2], fds, pid;

    if (*type != 'r' && *type != 'w' || type[1])
        return (NULL);

    if (pids == NULL) {
        if ((fds = getdtablesize()) <= 0)
            return (NULL);
        if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
            return (NULL);
        bzero((char *)pids, fds * sizeof(int));
    }
    if (pipe(pdes) < 0)
        return (NULL);
    switch (pid = vfork()) {
    case -1:            /* error */
        (void) close(pdes[0]);
        (void) close(pdes[1]);
        return (NULL);
        /* NOTREACHED */
    case 0:                /* child */
        if (*type == 'r') {
            if (pdes[1] != fileno(stdout)) {
                (void) dup2(pdes[1], fileno(stdout));
                (void) close(pdes[1]);
            }
            (void) close(pdes[0]);
        } else {
            if (pdes[0] != fileno(stdin)) {
                (void) dup2(pdes[0], fileno(stdin));
                (void) close(pdes[0]);
            }
            (void) close(pdes[1]);
        }
        execl("/bin/sh", "sh", "-c", program, NULL);
        _exit(127);
        /* NOTREACHED */
    }
    /* parent; assume fdopen can't fail...  */
    if (*type == 'r') {
        iop = fdopen(pdes[0], type);
        (void) close(pdes[1]);
    } else {
        iop = fdopen(pdes[1], type);
        (void) close(pdes[0]);
    }
    pids[fileno(iop)] = pid;
    return (iop);
}

int
pclose(iop)
    FILE *iop;
{
    register int fdes;
    sigset_t omask, nmask;
    union wait pstat;
    register int pid;

    /*
     * pclose returns -1 if stream is not associated with a
     * `popened' command, if already `pclosed', or waitpid
     * returns an error.
     */
    if (pids == NULL || pids[fdes = fileno(iop)] == 0)
        return (-1);
    (void) fclose(iop);
    sigemptyset(&nmask);
    sigaddset(&nmask, SIGINT);
    sigaddset(&nmask, SIGQUIT);
    sigaddset(&nmask, SIGHUP);
    (void) sigprocmask(SIG_BLOCK, &nmask, &omask);
    do {
        pid = waitpid(pids[fdes], (int *) &pstat, 0);
    } while (pid == -1 && errno == EINTR);
    (void) sigprocmask(SIG_SETMASK, &omask, NULL);
    pids[fdes] = 0;
    return (pid == -1 ? -1 : pstat.w_status);
}




相關推薦

Linux+Qt tar 命令GUI執行過程過程結果資訊捕捉

#!/bin/sh ls -Ral | grep -E "^(\-|d).*$" | grep -vE ".* (\.\.|\.)$" | wc -l 需求:Linux下使用GUI(qt)執行 tar 命令。需要顯示其過程和執行結果 設計:最初思路是想通過類似pv這樣的命令

Linux/Unixtar命令詳解

                tar命令是Linux/Unix系統下的打包壓縮工具,可以將多個檔案合併為一個檔案,打包後的檔案字尾為“.tar”。這裡首先需要明確兩個概念:打包和壓縮。打包是指將一大堆檔案或目錄合併成一個總的檔案;壓縮則是將一個大容量的檔案通過一些壓縮演算法(gzip、bzip2等命令)變成

(轉)linuxtar命令解壓到指定的目錄

轉自:http://blog.sina.com.cn/s/blog_62449fcf0100nfar.html linux下tar命令解壓到指定的目錄 : #tar zxvf /bbs.tar.zip -C /zzz/bbs   

Linuxtar命令詳解】

tar命令用於建立、還原備份檔案,它可以加入、解開備份檔案內的檔案。 引數 帶有*號的為常用的引數 . -A 新增壓縮檔案到已存在的壓縮包 . -c 建立新的壓縮檔案* . -d 記錄檔案的差別 . -r 向壓縮檔案的末尾追加檔案 . -u 更新原壓縮包中的檔案,新增改變了的現有檔案到已

Linuxtar命令總結

1. 壓縮命令 常用壓縮格式: .zip,.gz,.bz2,.tar.gz,.tar.bz2. 1.1 .zip格式壓縮 #壓縮檔案 zip 壓縮檔名 原始檔 #壓縮目錄 zip -r 壓縮檔名 源目錄 #解壓縮.zip檔案 unzip 壓縮檔

Linux centOS 7.2 命令 靜默安裝部署oracle11g資料庫

Linux  centOS命令列下 安裝部署oracle11g資料庫       小編今天給大家帶來Linux系統,Linux命令列下部署 oracle安裝部署資料庫,因為在Linux命令列來部署,所以在安裝部署oracle資料庫前,我們得進行檢查和設定,有以下步驟:一、檢查

Linux學習筆記--mv命令(剪或改名)

mv:英文名move,移動的意思。 1. 命令格式: mv [選項] 原始檔或目錄 目標檔案或目錄 mv [選項] 原始檔1 原始檔2 原始檔3 ... 目標目錄 2. 常用選項: "mv -b

Linux中目錄處理命令

touch abc:建立空檔案 rm abc:刪除空檔案 再輸入y就刪掉 rmdir 目錄名:這條刪目錄的命令一般不常用 mkdir -p japan.cangls:建立目錄japan,再在Japan裡面建立cangls目錄 rm -rf japan/:刪除目錄japan包括裡面的目錄,其中的-rf的f指的是

Ubuntutar命令詳解使用

格式: tar 選項檔案目錄列表 功能: 對檔案目錄進行打包備份 選項: -c 建立新的歸檔檔案 -r 向歸檔檔案末尾追加檔案 -x 從歸檔檔案中解出檔案 可以這樣記憶,建立新的檔案是c,追加在原有檔案上用r,從檔案中解壓出用x -O 將檔案解開到標準輸出 -v 處理過程中輸出相關資訊 -f 對普通檔案操作 

ubuntu16.04使用命令列編譯執行C++

使用vim或sublime編寫測試cpp檔案test.cpp例:#include<iostream> using namespace std; int main() { int a; cin>>a; cout<<a+

linux 輸入“make"命令不能執行

linu 執行 接下來 模式 vm 虛擬機 man 應該 size 驅動 我用的是VM 虛擬機的CDLinux,我想手動安裝網卡驅動。網卡驅動也已經復制到linux 系統中了。接下來應該輸入:makemake install可窗口提示:-bash:make :command

linux中的tar命令的使用

參考網址:   https://www.cnblogs.com/newcaoguo/p/5896975.html   https://www.cnblogs.com/xccjmpc/p/6035397.html 一. tar命令概述   1. 作用: tar命令是Unix/Linux系統中備份檔案(打

Linux壓縮打包tar命令總結

[email protected] mysql_db_backup]# tar -zcvpf - 2018-10-18/ | split -b 2M -d -a 1 - mysq.tar.gz. 2018-10-18/2018-10-18/last_lsn2018-10-18/incr/2018-1

Asp.net_解決vs執行報在安裝 32 位 Oracle 客戶端元件的情況以 64 位模式執行將出現此問題的bug方法

由於工作需要對原來一個專案做修改,結果遇到了麻煩。原來一般是在本機安裝32位的oracle客戶端,PLSQL Developer當時不支援64位,執行專案也沒問題。但是現在下載了個最新版的PLSQL Developer 64位版,安裝了oracle 64位的客戶端可以連線到

Linux系列之 tar 命令詳解

tar 是 unix/linux下的打包器 【解壓】 輸入命令: # tar  -zxvf  filename.tar.gz 引數解釋: z :表示 tar 包是被 gzip 壓縮過的 (字尾是.tar.gz),所以解壓時需要用 gu

Linux中通過KitchenPan以命令列方式執行kettle的JobTransformation

1. 準備工作 一個簡單的job,一個簡單的trans。 本處為了方便和效果易見,job和trans都生成檔案。 trans:讀取download目錄下的所有檔名,輸出為檔案。【介面情況下測試成功】 成功生成目標檔案: job:建立檔案。【介

linux解壓tar命令

引數: -c :建立一個壓縮檔案的引數指令(create 的意思); -x :解開一個壓縮檔案的引數指令! -t :檢視 tarfile 裡面的檔案! 特別注意,在引數的下達中, c/x/t 僅能存在一個!不可同時存在! 因為不可能同時壓縮與解壓縮。 -z :是否同時具有 gzip 的屬性?亦即是否需要用 g

Python 爬的必勝客資料背後藏著什麼樣的資訊

筆者從大學開始就接觸 Python,起初是好奇為什麼 Python 不需要瀏覽器就能抓取網站資料。深感奇妙之餘,也想親身體驗這種抓取資料的樂趣,所以寫了很多爬蟲程式。 後隨著知識面的拓展,開始瞭解到資料分析這一領域,方知道爬取到的資料背後原來還隱藏著一些資訊。自己也是在學習這

Linux開發時常用命令(用到時新增持續更新)

1、檔案許可權 r 可讀、w 可寫、x 可執行。 +表示增加許可權、-表示取消許可權、=表示唯一設定許可權。 u表示該檔案的擁有者、g表示與該檔案的擁有者屬於同一個群體(group)者、o表示其他以外的人、a表示這三者都是。 1)查詢檔案或資料夾的許可權 例如:

linux中單獨的test.sh可以執行將test.sh加入cron定時任務卻執行不成功(echo 導致)

問題: test.sh是一個爬蟲指令碼……單獨在終端執行 sh +x test.sh可以抓到資料,並儲存資料在資料庫;但是加入定時任務之後,只能抓到一條不全的資料……奇怪??!!! 排查: 雖然只是抓到不全的資料,但肯定定時任務沒問題,不是指