【Linux/Bash】stdin・stdout・stderrのリダイレクトとパイプを実例で解説
Linux/Bashのシェルには、コマンド実行時に利用できる3つのデータストリーム——stdin(標準入力)、stdout(標準出力)、stderr(標準エラー出力)が用意されています。この記事では、それぞれの役割と、リダイレクトやパイプを使った具体的な活用方法を解説します。
これらのstdin・stdout・stderrは、コンソールへのテキスト表示を担うだけでなく、各ストリームが出力するデータを別のプログラムへ渡すことも可能です。
これらは総称して標準ストリーム(Standard Streams)と呼ばれます。
stdin(標準入力)とは?
テキストを入力するためのストリームです。アプリケーションはstdin経由でテキストを受け取り、処理に利用できます。
stdout(標準出力)とは?
プログラムがテキストを出力するためのストリームです。アプリケーションはstdoutを通じて、別のプログラムへデータを送ったり、コンソール画面に結果を表示したりします。
stderr(標準エラー出力)とは?
プログラムがエラーメッセージを出力するためのストリームです。プログラムがエラーに遭遇した際は、その情報を通常の出力とは分離したstderrへ送るのが慣例となっています。
実際にはどういうこと?
コンピュータープログラムは、入力されたデータに対して何らかの処理を行い、結果を出力します。たとえば、数式を受け取ってその解を返すプログラムを想像してみてください。
このとき、数式をプログラム「の中へ」入れ、答えをプログラム「の外へ」取り出す仕組みが必要です。さらに、数式が解けなかった場合に備えて、エラーだけを他の出力と区別して確認できるようにしたいものです。
まさにそれを実現しているのが、stdin・stdout・stderrなのです。
すべてのコマンドラインアプリケーションが同じルールで動作すれば、扱いやすくなります。そこで、入力・出力・エラーの各ストリームは標準化され、CUI向けに作られたアプリケーションは皆同じ振る舞いをするようになりました。
だからこそ「標準」ストリームと呼ばれるのです。各ストリームには0〜2の番号(ファイルディスクリプタ)が割り当てられています。
| 番号 | ストリーム名 |
|---|---|
| 0 | stdin(標準入力) |
| 1 | stdout(標準出力) |
| 2 | stderr(標準エラー出力) |
Bashでのリダイレクトとパイプの基本
あなたがLinuxシェルに入力する文字もまた、テキストのストリームです。タイプした内容がコンソールの入力へ流れ込みます。
アプリケーションが実行されると、その出力テキストはコンソールへ送られ、画面に表示されることで読めるようになります。
これはコンソール作業におけるデフォルトの挙動ですが、変更することも可能です。ストリームはリダイレクトでき、たとえばプログラムの出力をコンソールではなくファイルへ直接書き込むことができます。
あるプログラムの出力を、別のプログラムの入力へ直接渡すこともできます。
以下、リダイレクトとパイプの基本的な例を見ていきましょう。
リダイレクト
通常、echoコマンドはテキストをコンソールに出力します。
echo "hello there!"
echoプログラムのstdoutは、デフォルトの経路である画面表示へ向かいます。
リダイレクトを使うと、この出力先を別の場所へ変更できます。ここではファイルへ送ってみます。
echo "hello there!" > test.txt
すると、「hello there!」というテキストを含むtest.txtというファイルが作成されます。注意:同名のファイルが既に存在する場合は上書きされるので気をつけてください。
上書きではなく追記したい場合は、>の代わりに>>を使用します。
次に、<を使ったstdinのリダイレクトを見てみましょう。
cat < test.txt
catコマンドはtest.txtの内容を自身のstdinへ読み込み、受け取ったデータをstdout(デフォルトではコンソール)へ出力します。つまり、この例では単純に「hello there!」がコンソールに表示されます。
ファイル内のデータがcatコマンドのstdinへ向けられた——つまりリダイレクトされたわけです。
厳密には、catコマンドは引数として渡されたファイル名を読み取る機能もあるため、この例は少し反則気味ですが、説明のためには最もシンプルなコマンドです。
stdinとstdoutは、同じコマンド内で同時にリダイレクトすることもできます。
cat < test.txt > output.txt
この例では、stdinがリダイレクトされてtest.txtの内容がcatプログラムへ読み込まれ、同時にcatプログラムのstdoutがoutput.txtというファイルへ書き込まれます。
これも実質的にはcatによるファイルコピーですが、他のコマンドの説明に依存しないシンプルな例として有効です。
最後に、stderrのリダイレクトです。読み取りたいストリームの番号を明示的に指定します(stdoutはデフォルトなので指定は不要です)。
cat nofile.txt 2> error.txt
「2」はstderrを表す番号です。catがエラーを生成した場合、そのメッセージはこのストリームを通じてerror.txtへ書き込まれます。
上記の例では、存在しないnofile.txtを開こうとして失敗するため、次の内容を含むerror.txtが作成されます。
cat: nofile.txt: No such file or directory
同時リダイレクト
前述のとおり、stderrは番号で識別できます。つまり、どちらをリダイレクトするか番号で指定すれば、stdoutとstderrを同じコマンド内で別々のファイルへ振り分けられます。
echo "hello there!" 1>test.txt 2>error.txt
この例では、stdout(番号1)がtest.txtへ、stderr(番号2)がerror.txtへそれぞれ送られます。
パイプ
パイプもリダイレクトの一種ですが、対象はstdinとstdoutのみで、エラー出力は無視されます。
echo "hello there!" | cat
ここでは、パイプ(|)によってechoコマンドのstdoutが、catコマンドのstdinへ接続されています。
まとめ
コマンドラインツールの操作は、最初は直感的でないと感じるかもしれませんが、タスク自動化において非常に強力な武器になります。stdin・stdout・stderrという標準ストリームこそがその柔軟性の礎であり、コマンドを連結して複雑なワークフローを構築すれば、ほぼあらゆる処理を自動化できるでしょう。
-
パズルを解きながらBashをマスターできる一冊――『Bash it out』レビュー
コンピューターは私にとって趣味であり、同時に仕事でもあります。自宅のアパートには10台ほどのマシンがあり、Macも含めてすべてLinuxが動いています。マシンのアップグレードもスキルの向上も好きな私にとって、Sylvain Leroux(シルヴァン・ルルー)氏の著書『Bash it out』を見つけたときは、迷わず購入しました。日頃からDebian Linuxでコマンドラインを多用している私にとって、Bashの知識を深める絶好の機会に思えたのです。しかも序文で著者自身がDebian Linuxを使っていると書かれており、私のお気に入りディストリビューションのひとつだけに、思わず笑みがこぼれまし
-
Bashシェル関数入門:実用的な6つのサンプル例で学ぶチュートリアル
Bashシェル関数とは、複数のUNIX/Linuxコマンドをひとつの名前でグループ化し、後からまとめて実行できるようにする仕組みです。Bashシェル関数は通常のUnixコマンドと同じように呼び出すことができ、現在のシェルコンテキスト内で実行されるため、解釈用の新しいプロセスを生成する必要がありません。bashのエイリアス(alias)と関数はどちらも、長いコマンドや複雑なコマンドに対するショートカットを定義するのに役立ちます。しかし、エイリアスでは制御フローや引数の扱いなど、関数ならではの高度な処理を行うことはできません。本記事では、その違いも含めて詳しく解説していきます。この記事は、進行中の