【ITニュース解説】Pipes and Redirection: How >, >>, 2> and | Really Work
2026年10月29日に「Dev.to」が公開したITニュース「Pipes and Redirection: How >, >>, 2> and | Really Work」について初心者にもわかりやすく解説しています。
ITニュース概要
シェルコマンドの「>」「>>」「2>」「|」は、入力・出力・エラーの3つの情報経路を制御する。標準出力は>でファイルへ上書き、>>で追記。エラーは2>でファイルへ。|は前のコマンドの出力を次のコマンドの入力に繋ぎ、複数の処理を連携させる。これらを理解すれば、シェルスクリプトの複雑なコマンドも読み解ける。
ITニュース解説
シェルコマンドを実行する際、>や|といった記号が並ぶと、複雑で理解しにくいと感じることがあるかもしれない。しかし、これらの記号は、コマンドが扱う文字情報の流れを制御するための非常に強力でシンプルな仕組みであり、その基本を理解すれば、どんなに長く複雑に見えるコマンドも読み解き、自分で作成できるようになる。
すべてのコマンドは、実行されるときに三つの異なる「ストリーム」を自動的に開く。これらは情報の流れを管理するための接続口のようなものだと考えると良い。一つ目は「標準入力(stdin)」で、コマンドが情報を読み込むためのストリームだ。デフォルトでは、キーボードからの入力がこの標準入力へと流れていく。このストリームには識別番号「0」が割り当てられている。二つ目は「標準出力(stdout)」で、コマンドが正常な処理結果などの情報を出力するためのストリームだ。デフォルトでは、この情報は画面に表示される。このストリームの識別番号は「1」だ。三つ目は「標準エラー出力(stderr)」で、コマンドがエラーメッセージなどの異常な情報を出力するためのストリームだ。これもデフォルトでは画面に表示される。このストリームの識別番号は「2」である。画面上では標準出力と標準エラー出力が区別なく表示されるため、同じように見えるかもしれないが、実際にはそれぞれ独立した二つのストリームであり、この分離が後述する多様な制御を可能にしている。リダイレクトはこれらのストリームの向きを変え、パイプは一つのコマンドの標準出力を次のコマンドの標準入力へと接続する。
まず、標準出力の向きを変える方法から説明しよう。>記号を使うと、コマンドの標準出力の行き先を、画面から指定したファイルへと変更できる。例えば、echo one > out.txtと実行すると、echoコマンドが出力する「one」という文字は画面には表示されず、「out.txt」というファイルに書き込まれる。もし「out.txt」が既に存在していた場合、そのファイルの内容は新しい出力で完全に上書きされてしまう。既存のファイルに情報を追記したい場合は、>>記号を使う。echo three >> out.txtとすると、「out.txt」の既存の内容の末尾に「three」という文字が追加される。毎回新しいファイルとして内容をクリアしたい場合は>を、ログファイルのように情報を蓄積していきたい場合は>>を使うと便利だ。
次に、標準エラー出力の向きを変える方法について説明する。前述の通り、標準エラー出力は識別番号2を持つ別のストリームである。そのため、標準出力のリダイレクトに使う>記号だけではエラーメッセージをファイルに保存できない。エラーメッセージをファイルに保存したい場合は、2>という記号を使う。例えば、ls nope fruits.txt > found.txt 2> errors.txtと実行すると、存在するファイル「fruits.txt」の情報は標準出力としてfound.txtに、存在しないファイル「nope」に関するエラーメッセージは標準エラー出力としてerrors.txtにそれぞれ別々に書き込まれる。この場合、画面には何も表示されない。エラーメッセージを完全に無視してどこにも保存したくない場合は、/dev/nullという特別なファイルにリダイレクトする。このファイルは、書き込まれた情報をすべて破棄する機能を持つため、ls nope fruits.txt 2> /dev/nullとすれば、エラーメッセージは画面にもファイルにも表示されず、完全に消滅する。
標準出力と標準エラー出力をまとめて同じ場所に送りたい場合もある。その場合は、2>&1という記号を使う。これは「ストリーム2(標準エラー出力)を、ストリーム1(標準出力)がいま向いているのと同じ場所に向けてください」という意味になる。例えば、ls nope fruits.txt > both.txt 2>&1と実行すると、標準出力と標準エラー出力の両方がboth.txtファイルに書き込まれる。ここで特に重要なのは、この> both.txt 2>&1という記述の順序だ。リダイレクトは左から右へ順に適用される。まず> both.txtが実行されて標準出力がboth.txtに向けられ、次に2>&1が実行されることで標準エラー出力が、そのboth.txtに向けられた標準出力と同じ場所(つまりboth.txt)に向けられる。もしこれをls nope fruits.txt 2>&1 > only.txtのように順序を入れ替えてしまうと、まず2>&1が実行された時点で標準出力はまだ画面に向けられているため、標準エラー出力も画面に向けられてしまう。その後で> only.txtが実行されて標準出力だけがonly.txtに向けられるため、エラーメッセージは画面に表示されたままだ。正しく両方をファイルに送るには、必ず> ファイル名 2>&1の順序で記述する必要がある。
複数のコマンドを連携させて、複雑な処理を効率的に実行したい場合は、|(パイプ)記号を使う。パイプは、左側のコマンドの標準出力を、間にファイルを挟むことなく、直接右側のコマンドの標準入力に接続し、情報を流す。これにより、それぞれのコマンドがシンプルな一つの役割に集中し、それらを組み合わせて大きな処理を実現できる。例えば、sort fruits.txt | uniq -c | sort -rnというコマンドは、「fruits.txtの行を並び替え(sort)、重複する行を数え(uniq -c)、最後にそのカウントが多い順に並び替える(sort -rn)」という一連の処理を、それぞれのコマンドが連携して実行する。パイプも標準出力のみを転送するため、左側のコマンドからエラーメッセージが出た場合、そのメッセージはパイプを通らず、画面に直接表示される。エラーメッセージも含めて次のコマンドに渡したい場合は、2>&1を使ってエラーも標準出力にマージしてからパイプで渡す必要がある。
コマンドの出力結果を画面で確認しつつ、同時にファイルにも保存したいという便利なケースもある。このような場合に役立つのがteeコマンドだ。teeは、標準入力から受け取った情報を、そのまま標準出力(画面)にも出しつつ、指定したファイルにも書き込む。例えば、echo hi | tee t.txtと実行すると、画面に「hi」が表示されると同時に、「t.txt」ファイルにも「hi」が書き込まれる。これは、時間がかかるコマンドの実行中に進捗状況を画面で見守りつつ、その全ログを後で確認するためにファイルに保存したい場合などに非常に重宝する。
システムエンジニアを目指す初心者が、これらの強力な機能を使いこなす上で、特に注意すべき二つのよくある間違いがある。一つ目は、「ファイルを自分自身にリダイレクトする」ことだ。例えば、sort fruits.txt > fruits.txtと実行すると、コマンドが開始する前にシェルがfruits.txtを空にしてしまうため、sortコマンドは何も読み込むことができず、結果としてfruits.txtは空っぽになってしまう。元のファイルを変更したい場合は、一度別のファイルにリダイレクトし、処理が完了した後に元のファイル名にリネームするのが安全な方法だ。二つ目は、sudoコマンドとリダイレクトを組み合わせる際に発生する権限の問題だ。例えば、sudo echo text > /etc/somefileと実行しても「Permission denied(権限がありません)」というエラーが出ることがある。これは、sudoがechoコマンドだけをroot権限で実行するのに対し、>によるファイルへの書き込みは、sudoの権限を持たない「あなたのシェル」が実行しようとするためだ。この問題を解決するには、echo text | sudo tee /etc/somefileのように、teeコマンドをsudoで実行し、teeにファイルへの書き込みを行わせる方法が正しい。
これらの記号が並んだ複雑なコマンドに出くわしたとき、一度にすべてを理解しようとする必要はない。むしろ、そのコマンドを小さな部品に分解して、一つずつ実行してみる習慣をつけると良い。まず最初のコマンドだけを実行して、何が出力されるかを確認する。次に、最初のコマンドとパイプの次のコマンドを合わせて実行し、その結果がどう変化するかを見る。このように段階的に試していくことで、それぞれの記号やコマンドがどのように情報を処理し、次のコマンドに渡しているのかが手に取るようにわかるようになる。このアプローチは、複雑なコマンドを理解するだけでなく、自分で新しい効率的なコマンドを作成する際にも非常に役立つ実践的な習慣となるだろう。