我可以复制管道的输出吗?

我可以复制管道的输出吗?

嗯,任务很简单:我的脚本的一部分必须计算 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]}

相关内容