ちょっとお酒も入ってる状態でシェル芸botで遊んでいた時、ふとteeで別プロセスに出力を渡す際にブレース展開を利用できないかと考えた。 teeコマンドといえば、パイプで受け付けた内容を指定したPATHのファイルと標準出力に渡してくれるコマンドで、プロセス置換を利用すれば同じ出力を別々のプロセスに渡せるのは有名でよく使われていると思うのだけど、その際にブレース展開をすることで短く書いてみようというのが今回の内容。 で、以下のようにevalをかます必要はあるけど可能なので記録として残しておく。

コマンド | eval tee ">(コマンド2 "{1..10}")" ">/dev/null"

何しているかわかりやすいよう、teeの箇所を抜き出してevalではなくechoを使って出力した例が以下。

blacknon@BS-PUB-DEVELOP:~$ echo -e tee ">(cat | grep ^"{1..3}")" ">/dev/null"
tee >(cat | grep ^1) >(cat | grep ^2) >(cat | grep ^3) >/dev/null
blacknon@BS-PUB-DEVELOP:~$ echo -e tee ">(cat | grep ^"{1..3}") \\\\\n" ">/dev/null"
tee >(cat | grep ^1) \
 >(cat | grep ^2) \
 >(cat | grep ^3) \
 >/dev/null

これをevalでコマンドとして実行すればよい。 で、どういう時に使うのか?という点について、とりあえず今回の場合の実行例。 例えば、以下のように「$PATHで補完されているコマンド一覧で、a-zそれぞれで始まるコマンドで最も短いものを抽出」をしたい時なんかに利用できる。

compgen -c | eval tee ">(cat|grep ^"{a..z}"|awk '{print length,\$0}'|sort -k1n|head -1)" ">/dev/null"|awk '{print $2}'|sort
blacknon@BS-PUB-DEVELOP:~$ compgen -c | eval tee ">(cat|grep ^"{a..z}"|awk '{print length,\$0}'|sort -k1n|head -1)" ">/dev/null"|awk '{print $2}'|sort
ar
bc
cc
dd
ed
fc
go
hd
id
jq
kill
l
mf
nc
od
pg
quote
ri
sg
tc
ul
vi
w
xz
yes
zic

ブレース展開して別プロセスに渡した後、各プロセスで処理をしないとあまり旨味のないやり方なので、ちょっと見にくくなるのは致し方なし…。