標準入出力とは - stdin / stdout / stderr の仕組み

標準入出力とは - stdin / stdout / stderr の仕組み

標準入出力って何だろう?

> file でログを保存したり、|(パイプ)でコマンドをつないだり——コマンドを学んでいくと、こういう記号に必ず出会う。その裏側にあるのが「標準入出力(stdin / stdout / stderr)」という仕組みだ。

この記事では、3つの標準入出力がそれぞれ何なのか、なぜ出力が2種類に分かれているのか、そしてリダイレクトやパイプで入出力先をどう切り替えるのかを、ライナとライニー先輩の会話でやさしく整理していく。

この記事でわかること

  • stdin / stdout / stderr の3つがそれぞれ何を担当しているか
  • なぜ出力が stdout と stderr の2種類に分かれているのか
  • 番号 0 / 1 / 2(ファイルディスクリプタ)の意味
  • > 2> &> で出力先を切り替える方法
  • パイプ | と入力リダイレクト < の使い方

1. 標準入出力とは何か?

結論: 標準入出力は、コマンドが「入力を受け取る口」と「結果を出す口」「エラーを出す口」の3つの標準的な通り道。それぞれ stdin / stdout / stderr と呼ぶ。

リナ: ライニー先輩、「標準入出力」って言葉を見かけたんですけど、なんだか難しそうで…
ライニー先輩: 名前はいかついけど、考え方はシンプルだよ。どんなコマンドにも「データが入ってくる口」と「結果を出す口」があるんだ。その標準的な通り道が3つあって、それぞれ名前がついている。
リナ: 3つもあるんですか?
ライニー先輩: そう。整理するとこうなるよ。
  • stdin(標準入力): コマンドにデータを渡す入り口
  • stdout(標準出力): 通常の結果を出す出口
  • stderr(標準エラー出力): エラーや警告を出す出口
リナ: 入り口が1つ、出口が2つ…なんですね。
ライニー先輩: その通り。普段は意識しなくても、コマンドは必ずこの3つの口を持って動いているんだ。

「標準」の意味

「標準」とは「特に指定しなければ使われる、決められた通り道」という意味。たとえば ls の結果が画面に出るのは、stdout の標準の行き先が画面(ターミナル)になっているから。この行き先を後から変えられるのが、リダイレクトやパイプの正体だ。

2. なぜ出力が stdout と stderr に分かれているの?

結論: 「次の処理に渡したい結果」と「人間に読ませたいエラー」を混ぜないため。分けておくと、結果だけを保存したりエラーだけを取り出したりできる。

リナ: でも、なんで出口が2つもあるんですか? ひとつにまとめたほうが楽じゃないですか?
ライニー先輩: いい疑問だね。例で考えてみよう。たくさんのファイルを処理して、結果をファイルに保存したいとする。もし「処理結果」と「エラーメッセージ」が同じ出口から出てきたら、保存したファイルの中にエラー文が混ざってしまうよね。
リナ: あ…たしかに。きれいな結果だけがほしいのに、ゴミが混ざっちゃう。
ライニー先輩: そう。だから Linux は最初から、
  • stdout = 正常な結果(次の処理やファイルに渡したいデータ)
  • stderr = エラーや警告(人間に知らせたいメッセージ)

を別々の出口にしている。こうしておけば、結果だけをファイルに保存しても、エラーはちゃんと画面に出て見落とさずに済むんだ。

リナ: なるほど! 役割で出口を分けてるんですね。

身近なたとえ

工場のラインで言えば、stdout は「完成品を流すベルトコンベア」、stderr は「不良品を知らせるアラーム」。完成品の箱(ファイル)にアラームの音は入れたくない。だから別々にしてある、というイメージ。

3. 番号 0 / 1 / 2 って何?

結論: stdin / stdout / stderr には 0 / 1 / 2 という番号(ファイルディスクリプタ)が割り当てられている。2>2 はこの番号のこと。

リナ: 設定例で 2> っていう書き方を見たんですけど、この 2 って何ですか?
ライニー先輩: それは stderr の番号なんだ。3つの標準入出力には、それぞれ整数の背番号がついている。
リナ: 背番号…?
ライニー先輩: 「ファイルディスクリプタ」っていう、コマンドが入出力の口を区別するための番号だよ。覚えるのは3つだけ。
番号 名前 役割
0 stdin 標準入力(入り口)
1 stdout 標準出力(通常の出口)
2 stderr 標準エラー出力(出口)

番号と記号の対応

リダイレクトの記号はこの番号と直結している。

  • >1> の省略形(stdout を送る)
  • 2> は stderr を送る
  • < 0< の省略形(stdin から読む)

2> の 2 は stderr の背番号」と覚えれば、記号の意味が一気に腑に落ちる。

4. リダイレクトで出力先を変えるには?

結論: > で stdout を、2> で stderr をファイルへ送れる。両方まとめるなら > file 2>&1 または &> file

リナ: 出口を分けてるのは分かりました。じゃあ、結果だけをファイルに保存するにはどうするんですか?
ライニー先輩: 「リダイレクト」を使うよ。出口の行き先を画面からファイルに付け替える操作だ。まずは stdout をファイルに保存してみよう。
ls /etc > filelist.txt

> を使うと、画面に出るはずだった stdout の内容が filelist.txt に書き込まれる(画面には何も出ない)。なお > は上書き、>> は追記になる。

エラーだけを保存したいときは 2> を使う。

ls /not-exist 2> errors.txt
(画面には何も出ず、errors.txt に次が記録される)
ls: cannot access '/not-exist': No such file or directory
リナ: stdout は >、stderr は 2> ですね。じゃあ、両方まとめて1つのファイルに入れたいときは?
ライニー先輩: そのときは 2>&1 を付け足す。「stderr(2)を stdout(1)と同じ行き先に流す」という意味だよ。
command > output.txt 2>&1

2>&1 は順番が大事

2>&1 は「stderr を、その時点での stdout の行き先に合わせる」という意味。そのため > output.txt先に書く必要がある。command 2>&1 > output.txt のように順番を逆にすると、stderr が古い行き先(画面)のまま残ってしまう。新しい &> file 記法(bash)なら順番を気にせず両方まとめられる。

command &> output.txt

5. パイプと標準入力はどう使う?

結論: パイプ | は左コマンドの stdout を右コマンドの stdin につなぐ。< はファイルの中身を stdin として渡す。

リナ: stdin(入り口)はいつ使うんですか? あまり意識したことがなくて…
ライニー先輩: 実はパイプを使うとき、裏で stdin が大活躍してるんだ。パイプ | は、左のコマンドの stdout を、右のコマンドの stdin に直接つなぐ仕組みなんだよ。
ls /etc | grep conf

この例では、ls /etc の出力(stdout)が、そのまま grep conf の入力(stdin)に流れ込む。grep はその入力の中から conf を含む行だけを拾い出す。

流れのイメージ

ls /etc  ──stdout──▶  |  ──stdin──▶  grep conf  ──stdout──▶  画面

パイプは「前のコマンドの出口」と「次のコマンドの入り口」を直結するホースのようなもの。

ファイルの中身を stdin として渡したいときは < を使う。

sort < names.txt

これは names.txt の中身を sort の標準入力に流し込み、並べ替えて表示する。sort names.txt と結果は同じだが、「ファイルを stdin につなぐ」という標準入力の動きが分かりやすい例だ。

パイプやリダイレクトをもっと実践的に練習したいなら、パイプとリダイレクトの基本 で手を動かしながら学べる。出力を画面とファイルの両方に出したいときは tee コマンドの使い方 も便利だ。

まとめ

  • 標準入出力は stdin(入力)/ stdout(通常の出力)/ stderr(エラー出力)の3つの通り道
  • 出力が2種類あるのは「結果」と「エラー」を混ぜないため
  • 3つには番号 0 / 1 / 2(ファイルディスクリプタ)が割り当てられている
  • > で stdout、2> で stderr をファイルへ送れる(両方なら > file 2>&1 または &> file
  • パイプ | は stdout を次の stdin につなぎ、< はファイルを stdin として渡す

次に読む