忙しい人向けのまとめ
pee
コマンドは標準出力を複数のコマンドに同時にパイプできるよ!
teeコマンドってあるじゃん?
tee
というコマンドがありますよね。標準入力を標準出力と同時に、ファイルに書き出すコマンドです。よく使うのは、コマンドの出力をroot権限でファイルに書き出したい場合でしょう。
例えば、以下のコマンドは「echoの出力を/etc以下に(root権限で)書き込みたい」という時に初心者がやりがちな間違いです。意図はわかるのですが、この場合 echo
コマンドが(無意味に)root権限で起動するものの、リダイレクトはシェルを動かしている一般ユーザー権限で実行されるため、無慈悲にもPermission deniedとなります。
$ sudo echo hoge > /etc/fuga
これを意図通りに動かすには、/etc
以下に書き込むプロセスをroot権限で起動する必要があります。そこで登場するのが tee
コマンドなわけです。上記の間違いを tee
を使って書き直すと以下のようになります。
$ echo hoge | sudo tee /etc/fuga
そして tee
コマンドは、標準入力を複数のファイルに同時に書き込むこともできます。以下の例では、/etc/fuga /
etc/piyo
/etc/foo
/etc/bar
という四つのファイルに、同じ内容が書き込まれます。
$ echo hoge | sudo tee /etc/{fuga,piyo,foo,bar}
peeはteeのパイプ版
標準入力の内容をファイルに書き出す tee
コマンドに対し、パイプに書き出すのが pee
コマンドです*1。
ここまで聞くと「標準入力をパイプに書き出す? 普通にパイプ繋げばいいじゃん」と思うでしょう。pee
コマンドの真価は、tee
と同様に、出力先を複数指定できるところにあります。
例えばこんな使い方はどうでしょう。
ps
コマンドの出力を grep
して、特定のプロセスの情報だけを表示したいことがよくあります。こんな感じですね。
$ ps -fe | grep '[z]sh' mizuno 1413882 1413881 0 11:11 pts/0 00:00:01 -zsh
はい、複数のカラムに色々な情報が表示されましたが、この数字って何の意味でしたっけ? ps
コマンドは一行目にヘッダが表示されるのですが、プロセス名で grep
してしまうと、当然ヘッダは表示されません。そこで一行目だけを表示する、head
コマンドと同時にパイプしてみましょう。
$ ps -fe | pee "head -n 1" "grep [z]sh" UID PID PPID C STIME TTY TIME CMD mizuno 1413882 1413881 0 11:11 pts/0 00:00:01 -zsh
ps
コマンドの出力が、head
と grep
それぞれにパイプされ、期待した出力を得ることができました。
なに? grep
の条件を複数指定してor検索すればいいじゃんって? ぎゃふん。
それはさておき、コマンドを直列に繋ぐパイプを並列に分岐させられるのは、色々な使い途がありそうです。ただしそれぞれのコマンドの終了順は保証されていないようなので、そこだけは留意する必要がありそうですね。
ちなみに pee
は、Ubuntuでは moreutils
パッケージに含まれています。このパッケージには色々と便利なコマンドが含まれているので、興味があったら見てみてください。筆者のお勧めは vidir
vipe
sponge
です。
*1:これは「pipeのtee」の略であり、決しておしっこではないと思います。たぶん。