私はこれを持っています:
tee < /some/big/file >(wc -c) >(md5sum) | ...
wc -c
との結果を stdout に書き込む代わりにmd5sum
、後で処理するために結果を 2 つの変数に格納したいと考えています。ファイルを複数回読みたくありません。どうすればそれを達成できますか?
これはあなたの質問に直接答えるものではありません...しかし、ファイルを一度だけ読む必要があり、使用する必要はありません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
これは、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
誰かがもっと良いものを提供できるかもしれませんが、あなたのベストショットは
LINES=$(cat /some/big/file | wc -l)
MD5=$(cat /some/big/file | md5)
その理由は、これが最善の方法だと思いますが、何らかの方法でファイルの内容に 2 つの別々の操作を適用する必要があるからです。したがって、同時にそれを実行する方法を知っているコマンドがない限り、それを 2 回読む必要があります。2回読むだけでなく、問題の解決策になるはずです。
>()
(プロセス置換)から変数をエクスポートできるとは思いません。出力を一時ファイルにリダイレクトしても構わない場合は、ファイルを変数に読み込むことができます。
例
tee < /some/big/file >(cmd1 > tmp1) >(cmd2 > tmp2) | ...
CMD1_OUT=$(cat tmp1)
CMD2_OUT=$(cat tmp2)