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

リダイレクトとパイプ

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

リダイレクトとパイプは、コマンドの入力と出力の通り道を自由につなぎ替えるための仕組みだ。

コマンドの結果は、当たり前のように画面に出る。だが、その出力先は固定ではない。

💡
ポイントリダイレクトとパイプは、入力と出力の通り道をつなぎ替える仕組み。出力をファイルへ送ったり、コマンド同士を直結したりできる。

Linuxのコマンドには、入力と出力の通り道があらかじめ決められている。キーボードからの入力を受け取る標準入力、結果を画面に出す標準出力、そしてエラーメッセージを出す標準エラー出力の3つだ。

ここに大きな力が隠れている。これらの通り道は固定ではなく、自由につなぎ替えられるのだ。出力をファイルに保存したり、ファイルの中身をコマンドに食わせたり、あるコマンドの出力を別のコマンドの入力に直結したりできる。

この入出力のつなぎ替えを支えるのがリダイレクトとパイプだ。小さなコマンドを部品として組み合わせ、複雑な処理を作り上げるLinux流のやり方は、この仕組みの上に成り立っている。

🔢 3つの通り道と番号

3つの通り道には、それぞれ0、1、2という番号(ファイルディスクリプタ)が割り当てられている。標準入力が0、標準出力が1、標準エラー出力が2だ。

コマンド標準入力0標準出力1標準エラー出力2

ふだんは標準入力がキーボード、標準出力と標準エラー出力がどちらも画面につながっているため、結果もエラーも同じ画面に混ざって表示される。

だが重要なのは、通常の結果(標準出力)とエラーメッセージ(標準エラー出力)が、見た目は同じ画面でも内部的には別の流れだという点だ。この2つを別々に扱えることが、ログの整理やエラーの切り分けで効いてくる。

💡
ポイント標準入力0・標準出力1・標準エラー出力2。結果とエラーは見た目は同じ画面でも、内部的には別の流れだ。

リダイレクトの記号に出てくる 1 や 2 は、この番号を指していると理解しておくと、後の話がすっと入ってくる。

⚠ > は上書きするから怖い

コマンドの標準出力を画面ではなくファイルへ向けるのがリダイレクトだ。> はファイルへの上書き保存で、echo "1行目" > log.txt とすると log.txt に「1行目」が書き込まれる。

ここで強く意識してほしいことがある。> は対象ファイルに中身があっても問答無用で上書きし、元の内容を消してしまうのだ。大事なファイルを誤って > で空にしてしまう事故は少なくない。

つまずき> は中身があっても問答無用で上書きし、元の内容を消す。追記したいときは >> を使う。取り違え事故が多い。

これに対して >> は末尾への追記で、echo "2行目" >> log.txt とすれば既存の内容を残したまま後ろに行を足す。

> 上書き元の内容新しい内容元は消える>> 追記元の内容+ 後ろに追加元は残る

「新規に作り直す・上書きするなら >、すでにある内容に足していくなら >>」という使い分けを徹底すると、うっかりファイルを潰す事故を防げる。

逆に、ファイルの中身をコマンドの標準入力として読み込ませたいときは < を使い、command < input.txt のように書く。

🔀 エラーだけを別に扱う

エラーメッセージだけを別に扱いたいときは、標準エラー出力の番号2を使う。2> file と書くと、エラーメッセージだけをファイルに保存できる。

たとえば some_command 2> error.log とすれば、通常の結果は画面に出したまま、エラーだけを error.log に振り分けられる。

some_command 2> error.log ……通常の結果は画面に出したまま、エラーメッセージだけを error.log に振り分ける。

一方、エラーも通常の出力と同じ場所へまとめたいときは 2>&1 と書く。これは「2番(標準エラー出力)を、1番(標準出力)と同じ行き先へ合流させる」という意味だ。さきほど番号を覚えた意味が、ここで効いてくる。

たとえば command > all.log 2>&1 とすれば、結果もエラーもすべて all.log にまとめて記録できる。

コツ結果もエラーもまとめたいなら 2>&1。command > all.log 2>&1 の順で書くのが定石。順序に意味がある。

この 2>&1 はパイプと組み合わせても使われ、ls /etc /no/such 2>&1 | head のように書くと、エラーメッセージも含めて後続のコマンドに流せる。書く順序には意味があり、> all.log 2>&1 の順で書くのが定石だ。

🔗 コマンドとコマンドを直接つなぐ

リダイレクトがコマンドとファイルの間をつなぐのに対し、パイプ | はコマンドとコマンドを直接つなぐ。前のコマンドの標準出力を、ファイルを経由せずそのまま次のコマンドの標準入力へ流し込む仕組みだ。

ls -l一覧を出すgrep txt絞り込むwc -l数える||前の出力を、ファイルを経由せず次の入力へ流し込む

たとえば ls | grep txt と書くと、ls が出力したファイル一覧が grep に渡され、その中から txt を含む行だけが抜き出される。grep は受け取った入力から条件に合う行を絞り込むコマンドだ。

ls -l | grep txt | wc -l ……一覧を出す→絞り込む→数える、と小さな処理を数珠つなぎにできる。パイプはいくつでもつなげる。

パイプは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 というファイル」に書き込んでしまう。

つまずきパイプ | はコマンドへ、リダイレクト > はファイルへ。ls > grep txt は grep へつながらず、grep というファイルに書き込む。

さらに、エラーが出ているはずなのにファイルに記録されないという悩みは、2> や 2>&1 でエラー出力を取り込んでいないのが原因のことがほとんどだ。

なお、出力やエラーが不要で捨ててしまいたいときは /dev/null という特別な行き先が使える。これは書き込んだものをすべて捨てるごみ箱のような存在で、command 2> /dev/null と書けばエラーメッセージだけを画面に出さずに捨てられるし、command > /dev/null 2>&1 とすれば結果もエラーもまとめて捨てられる。定期実行のスクリプトなどで余計な出力を抑えたいときに重宝する。

コツ/dev/null は捨て先のごみ箱。command > /dev/null 2>&1 で結果もエラーもまとめて捨てられる。定期実行で出力を抑えるのに便利。

これらを押さえれば、入出力の流れを自在に組み立てられるようになる。

この項目に出てくる用語

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

関連コマンド

echocat

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