2

我有这个:

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

我不想将结果写入标准输出,而是将结果存储到两个变量中以供以后wc -c处理。md5sum我不想多次阅读该文件。我怎样才能做到这一点?

4

4 回答 4

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
于 2013-05-10T02:02:12.783 回答
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(或catwc -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
于 2013-05-10T01:45:27.193 回答
0

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

例子

tee < /some/big/file >(cmd1 > tmp1) >(cmd2 > tmp2) | ...
CMD1_OUT=$(cat tmp1)
CMD2_OUT=$(cat tmp2)
于 2013-05-10T02:04:39.660 回答
0

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

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

我认为这是最好的选择,原因是您必须以一种或另一种方式对文件的内容应用两个单独的操作。因此,除非您有一个知道如何同时执行的命令,否则您将不得不阅读它两次。除了阅读两次之外,这应该是解决您问题的方法。

于 2013-05-10T01:35:45.147 回答