我有这个:
tee < /some/big/file >(wc -c) >(md5sum) | ...
我不想将结果写入标准输出,而是将结果存储到两个变量中以供以后wc -c
处理。md5sum
我不想多次阅读该文件。我怎样才能做到这一点?
您可以使用 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
这并不能直接回答您的问题...但是您只需阅读一次文件,而不必使用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
我认为您不能从>()
(Process 替换)中导出变量。如果您不介意将输出重定向到临时文件,则可以将文件读入变量。
例子
tee < /some/big/file >(cmd1 > tmp1) >(cmd2 > tmp2) | ...
CMD1_OUT=$(cat tmp1)
CMD2_OUT=$(cat tmp2)
可能有人可以提供更好的东西,但我认为你最好的选择是
LINES=$(cat /some/big/file | wc -l)
MD5=$(cat /some/big/file | md5)
我认为这是最好的选择,原因是您必须以一种或另一种方式对文件的内容应用两个单独的操作。因此,除非您有一个知道如何同时执行的命令,否则您将不得不阅读它两次。除了阅读两次之外,这应该是解决您问题的方法。