如何在变量中将>()内的Bash命令输出存储?

时间:2013-05-10 01:24:57

标签: bash shell

我有这个:

tee < /some/big/file >(wc -c) >(md5sum) | ...

我没有将wc -cmd5sum的结果写入stdout,而是希望将结果存储到两个变量中以便以后处理。我不想多次读取该文件。我怎么能做到这一点?

4 个答案:

答案 0 :(得分:1)

这不会直接回答您的问题...但您只需阅读一次文件,而不必使用tee

SIZE=$(wc -c /some/big/file)
MD5=$(md5 /some/big/file)

那么,这次读取文件的次数是多少?一旦。这是因为wc -c实际上并没有读取文件,只是查看它有多长并报告回来。以下是我的测试:

$ time wc -c /big/file >/dev/null
real    0m0.003s
user    0m0.000s
sys     0m0.000s
$ time wc -c </big/file >/dev/null
real    0m0.004s
user    0m0.000s
sys     0m0.000s
$ time cat /big/file | wc -c >/dev/null
real    0m52.945s
user    0m0.160s
sys     0m19.612s

课程:不要将tee(或cat)与wc -c混在一起,因为这是浪费时间的。只需正常执行md5,不要担心wc -c

注意:wc -c <file速度快的原因是因为它获得了普通的文件句柄,就像wc本身调用了open()一样。

管道性能

你几乎不应该在管道中使用cat

cat file | cmd    # slow
cmd <file         # fast

调用cat通常意味着创建一个无用的额外流程。在某些情况下,与wc -c一样,它实际上会在管道之后减慢程序的速度。我的意思是,你可以把cat贴在你喜欢的任何地方,但这只是愚蠢的:

echo 'hello, world' | cat
cat file.txt | less
cat file.txt | cat | less
cat file.txt | cat | sort | cat | cat | uniq | cat >file_unique.txt

这样更好:

echo 'hello, world'
less file.txt
sort file.txt | uniq >file_unique.txt

答案 1 :(得分:1)

您可以使用FIFO和临时文件执行此操作。

input=/some/big/file
mkfifo tmp
wc -l <tmp >wc.out &
md5=$(tee <"$input" tmp | md5sum)
fg
lines=$(cat wc.out)
rm tmp
rm wc.out

答案 2 :(得分:0)

可能有人可以提供更好的东西,但我认为你的最佳镜头是

LINES=$(cat /some/big/file | wc -l)
MD5=$(cat /some/big/file | md5)

我认为这是最佳镜头的原因是,无论如何,您必须对文件内容应用两个单独的操作。因此,除非你有一个知道如何同时执行它的命令,否则你必须阅读它两次。 除了阅读两次之外,这应该是解决问题的方法。

答案 3 :(得分:0)

我认为您不能从>()Process substitution)导出变量。如果您不介意将输出重定向到临时文件,则可以将文件读入变量。

实施例

tee < /some/big/file >(cmd1 > tmp1) >(cmd2 > tmp2) | ...
CMD1_OUT=$(cat tmp1)
CMD2_OUT=$(cat tmp2)