我可以複製管道的輸出嗎?

我可以複製管道的輸出嗎?

嗯,任務很簡單:我的腳本的一部分必須計算 md5 和 sha1 雜湊。輸入是一個檔案(大檔案),必須將雜湊值放入 M​​D 和 SH 變數中以供以後的輸出組合。

雖然處理的檔案非常大(數百 GB),但我嘗試使用某種讀取後多次使用的資料。我發現了一種叫做流程替換的東西,我以下面的方式採用了它:

$ dd if=big.tgz 2>/dev/null |tee >(sha1sum ) > >(md5sum ) ;

代替:

$ SH=$(sha1sum big.tgz); MD=$(md5sum big.tgz);

但我發現了下一個:

  • 顯然沒有資源,也沒有節省時間,因為兩者都需要大約。 40 秒(適用於 4.776 GB 檔案)

  • 我不知道如何將子進程的結果保存>(md5sum )到變數 MD 中以便稍後在腳本中使用它

我試圖理解 pipelinexec,但即使是漂亮的彩色插圖也沒有成功。

除了 VAR=$(command) 之外,還有其他方法可以將輸出重新導向到變數嗎?

答案1

在效能方面,您可能會受到 CPU 的限制。實際上,MD5 和 sha1sum 在 40 秒內傳輸 4.7TB 感覺很快。所以即使你這樣工作。值得一提的是,您將減少磁碟 IO。

你真的不需要這樣做dd。您也可以將 sha1sum 和 md5sum 的輸出直接寫入檔案以供以後使用

tee < big.tgz  >(sha1sum > big.tgz.sha1 ) > >(md5sum > big.tgz.md5 )
sha1=`cat big.tgz.sha1`
md5=`cat big.tgz.md5`

我建議使用像這樣的臨時檔案(big.tgz.sha1big.tgz.md5),因為據我所知,沒有辦法同時設定兩個具有不同值的變數。您可以將其中一個直接捕獲到變數中,但不能同時捕獲兩者。允許md5sumsha1sum同時寫入同一個標準輸出可能會導致不可預測的問題。

答案2

好吧,你可以在裡面添加另一個重定向:

tee < big.tgz >(sha1sum > big.tgz.sha1sum) >(md5sum > big.tgz.md5sum)

您也可以按原樣獲取輸出,因為很容易區分 sha1 和 md5(長度不同,因此不會混淆哪個是哪個)。

還有一些實用程式可以自行計算多個校驗和,而無需使用tee.

實際上上面的內容也可以不寫tee

sha1sum big.tgz > big.tgz.sha1sum &
md5sum big.tgz > big.tgz.md5sum
wait # for sha1sum

從理論上講,這很糟糕,因為資料從磁碟讀取兩次。

實際上,並行(和後台)運行兩個讀取器應該允許磁碟快取來處理它,以便資料實際上仍然只讀取一次。這假設雜湊計算很快而 I/O 很慢,因此沒有進程可以逃離另一個進程。

(我之前發布過關於在另一個上下文中閱讀兩次的文章:將 pv 與 md5sum 一起使用- 雖然它通常有效,但存在一些風險,因此tee仍然是更可靠的方法。 )

答案3

parsetGNU Parallel 用於並行設定變量,並將--tee輸入傳送到多個命令:

parset md5,sha1,sha256 --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo $sha1

parset sumarr --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo ${sumarr[1]}

相關內容