我有这个:
tee < /some/big/file >(wc -c) >(md5sum) | ...
我没有将wc -c
和md5sum
的结果写入stdout,而是希望将结果存储到两个变量中以便以后处理。我不想多次读取该文件。我怎么能做到这一点?
答案 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)