🐧 Linux 総合学習プラットフォーム
シェルスクリプト ・ 中級

リダイレクトとパイプ

コマンドの入出力は自由につなぎ替えられます。> は標準出力をファイルへ上書き保存、>> は末尾へ追記、< はファイルを標準入力として読み込みます。エラーメッセージ(標準エラー出力)は 2> で分けて保存でき、2>&1 で標準出力と同じ流れに合流させます。パイプ | は前のコマンドの出力を次のコマンドの入力へ直接渡す仕組みで、ls | grep txt のように小さな道具をつないで処理を組み立てます。

Linuxのコマンドは、入力と出力の通り道があらかじめ決められています。キーボードからの入力を受け取る標準入力、結果を画面に出す標準出力、そしてエラーメッセージを出す標準エラー出力の3つです。これらの通り道は固定ではなく、自由につなぎ替えられるところにLinuxの大きな力があります。出力をファイルに保存したり、ファイルの中身をコマンドに食わせたり、あるコマンドの出力を別のコマンドの入力に直結したり——この入出力のつなぎ替えを支えるのがリダイレクトとパイプです。小さなコマンドを部品として組み合わせ、複雑な処理を作り上げるLinux流のやり方は、この仕組みの上に成り立っています。

標準入力・標準出力・標準エラー出力

3つの通り道には、それぞれ0、1、2という番号(ファイルディスクリプタ)が割り当てられています。標準入力が0、標準出力が1、標準エラー出力が2です。ふだんは標準入力がキーボード、標準出力と標準エラー出力がどちらも画面につながっているため、結果もエラーも同じ画面に混ざって表示されます。重要なのは、通常の結果(標準出力)とエラーメッセージ(標準エラー出力)が、見た目は同じ画面でも内部的には別の流れだという点です。この2つを別々に扱えることが、ログの整理やエラーの切り分けで効いてきます。リダイレクトの記号に出てくる 1 や 2 は、この番号を指していると理解しておくと、後の話がすっと入ってきます。

出力をファイルへ — > と >>

コマンドの標準出力を画面ではなくファイルへ向けるのがリダイレクトです。> はファイルへの上書き保存で、echo "1行目" > log.txt とすると log.txt に「1行目」が書き込まれます。ここで強く意識してほしいのは、> は対象ファイルに中身があっても問答無用で上書きし、元の内容を消してしまうことです。大事なファイルを誤って > で空にしてしまう事故は少なくありません。これに対して >> は末尾への追記で、echo "2行目" >> log.txt とすれば既存の内容を残したまま後ろに行を足します。「新規に作り直す・上書きするなら >、すでにある内容に足していくなら >>」という使い分けを徹底すると、うっかりファイルを潰す事故を防げます。逆に、ファイルの中身をコマンドの標準入力として読み込ませたいときは < を使い、command < input.txt のように書きます。

エラー出力を分ける — 2> と 2>&1

エラーメッセージだけを別に扱いたいときは、標準エラー出力の番号2を使います。2> file と書くと、エラーメッセージだけをファイルに保存できます。たとえば some_command 2> error.log とすれば、通常の結果は画面に出したまま、エラーだけを error.log に振り分けられます。一方、エラーも通常の出力と同じ場所へまとめたいときは 2>&1 と書きます。これは「2番(標準エラー出力)を、1番(標準出力)と同じ行き先へ合流させる」という意味です。たとえば command > all.log 2>&1 とすれば、結果もエラーもすべて all.log にまとめて記録できます。この 2>&1 はパイプと組み合わせても使われ、ls /etc /no/such 2>&1 | head のように書くと、エラーメッセージも含めて後続のコマンドに流せます。書く順序には意味があり、> all.log 2>&1 の順で書くのが定石です。

パイプ | で出力を次のコマンドへ渡す

リダイレクトがコマンドとファイルの間をつなぐのに対し、パイプ | はコマンドとコマンドを直接つなぎます。前のコマンドの標準出力を、ファイルを経由せずそのまま次のコマンドの標準入力へ流し込む仕組みです。たとえば ls | grep txt と書くと、ls が出力したファイル一覧が grep に渡され、その中から txt を含む行だけが抜き出されます。grep は受け取った入力から条件に合う行を絞り込むコマンドです。パイプは2つに限らず、ls -l | grep txt | wc -l のようにいくつでも数珠つなぎにでき、「一覧を出す→絞り込む→数える」のように小さな処理を段階的に重ねられます。これがLinuxの設計思想の核で、ひとつのことだけをうまくこなす小さなコマンドを、パイプで組み合わせて大きな仕事をこなす、という考え方です。

組み合わせの実例とよくある失敗

リダイレクトとパイプは、組み合わせることで実務の力を発揮します。たとえば ps aux | grep nginx でプロセス一覧から目的のものだけを絞り込み、cat access.log | grep error > errors.txt でログからエラー行だけを抜き出してファイルに保存する、といった使い方が日常的に登場します。複数行をまとめてファイルに渡したいときは、ヒアドキュメント(here-doc)も便利です。cat <<EOF > memo.txt のように書くと、次に単独の EOF が現れる行までの内容を、まとめて memo.txt に書き込めます。設定ファイルを一気に生成するときの定番です。最後によくある失敗を挙げておきます。最も多いのが、追記のつもりで > を使ってファイルを上書きしてしまう取り違えです。続いて、パイプとリダイレクトの混同——パイプ | はコマンドへ、リダイレクト > はファイルへ渡すもので、ls > grep txt のように書いても grep へはつながらず「grep というファイル」に書き込んでしまいます。さらに、エラーが出ているはずなのにファイルに記録されないという悩みは、2> や 2>&1 でエラー出力を取り込んでいないのが原因のことがほとんどです。なお、出力やエラーが不要で捨ててしまいたいときは /dev/null という特別な行き先が使えます。これは書き込んだものをすべて捨てるごみ箱のような存在で、command 2> /dev/null と書けばエラーメッセージだけを画面に出さずに捨てられますし、command > /dev/null 2>&1 とすれば結果もエラーもまとめて捨てられます。定期実行のスクリプトなどで余計な出力を抑えたいときに重宝します。これらを押さえれば、入出力の流れを自在に組み立てられるようになります。

この項目に出てくる用語

リダイレクトりだいれくと
コマンドの入出力をファイルへ向け替える仕組み。> < >> など。
パイプぱいぷ
前のコマンドの出力を次のコマンドの入力へ渡す | のこと。
標準エラー出力ひょうじゅんえらーしゅつりょく
エラーメッセージが流れる出力先。番号は2で、標準出力(1)とは別。

関連コマンド

echocat

▶ 学習アプリでこの続きを学ぶ・演習する