3秒でわかる
あるコマンドの出力を次のコマンドの入力へ直接つなぐ記号。小さな道具を組み合わせて、絞り込みや集計を1行で組み立てられます。
もう少し詳しく
どういうものか
| はパイプと呼ばれ、左のコマンドの標準出力を右のコマンドの標準入力へそのまま流し込みます。中間ファイルを作らずにメモリ上で受け渡されるため、左が出した行を右がすぐ処理し始めます。
Unix 系のコマンドが「1つのことだけをやり、結果を行で吐く」という作りになっているのは、パイプで数珠つなぎにする前提があるからです。個々のコマンドは小さいまま、組み合わせで目的の集計を作ります。
なぜ必要か
ログから特定の文字を含む行を数える、という作業を1つの巨大なコマンドで用意しようとすると、条件の数だけオプションが増えます。パイプがあれば「取り出す」「絞る」「並べる」「数える」を別々のコマンドに任せ、必要な順に並べるだけで済みます。覚えるのはコマンド数個と | の意味だけです。
具体例
# アクセスログから 500 番台の行を抜き、多い URL を上位5件
cat access.log | grep " 500 " | awk '{print $7}' | sort | uniq -c | sort -nr | head -5
# プロセス一覧から nginx を含む行だけ見る
ps aux | grep nginx
# ファイル数を数える
ls -1 | wc -lつなぐたびに手元のデータが絞られていく様子を、1段ずつ実行して確かめると理解が速くなります。
つまずきやすいところ
パイプが運ぶのは標準出力だけで、標準エラー出力は流れません。エラーメッセージを含めて次に渡すなら 2>&1 | と書くか、bash なら |& を使います。エラーだけ画面に出て「grep が効かない」と見えるのは、この取りこぼしが原因です。
終了ステータスも落とし穴です。既定では最後のコマンドの結果しか返らないため、途中が失敗しても全体は成功扱いになります。スクリプトでは set -o pipefail を付けて、途中の失敗を拾えるようにします。
sudo の位置も間違えやすい点です。cat file | sudo tee out は書き込み側に権限が渡りますが、sudo cat file | tee out では書き込み側が一般ユーザーのままです。権限が要るのはどちらのコマンドかを見て置き場所を決めます。
似た用語との違い
| 記号 | 行き先 | 用途 | |
|---|---|---|---|
\ | 次のコマンドの標準入力 | 加工を数珠つなぎにする | |
> | ファイル (上書き) | 結果を残す | |
>> | ファイル (追記) | ログを足していく | |
< | コマンドの標準入力 | ファイルを食わせる |
覚え方
パイプは配管です。データを水と見立て、grep はフィルター、sort は整流器、wc はメーターに相当します。