標準入出力

標準入出力とは

シェルによって実行されるコマンドには標準入出力というデータの通り道が用意されている。
このデータの通り道を様々な方向に切替えることによって複数のコマンドを組み合わせて複雑な操作を行なうことができるようになる。
データの通り道の種類には以下のものがある。

標準入力
コマンドのためにデータ入力用として用意されているデータの通り道のことである。
普通は標準入力の入力元はキーボードになる。
データを入力する必要のある多くのコマンドでは、引数にファイル名を付けないと標準入力からデータを入力する。
C言語では、標準入力からscanfによってデータを読み込む。
lsのように標準入力の無いコマンドもある。
標準出力
コマンドがデータを出力するために用意されているデータの通り道のことである。
普通は標準出力の出力先はウインドウ(kterm、コンソール)になる。
lsその他の多くのコマンドが結果の標準出力に出力する。
C言語では、printfによってデータを標準出力に出力する。
[標準入力と標準出力の図]
[→] : 標準入力
[→] : 標準出力
標準エラー出力
異常な状態などが起こった場合にエラー表示をするために使用される、標準出力とは別のデータの通り道である。
lsでファイルが見つからなかった時、ccでエラーが起こった場合などに標準エラー出力に出力する。
C言語などでプログラムを作る場合には、正しく計算できたデータは標準出力に出力し、データが見つからない、計算結果がおかしい、などの場合には標準エラー出力からエラーメッセージを出力する。
C言語では fprintf(stderr, ...)などを使うと標準エラー出力にデータを出力することができる。 (stderrが標準エラー出力を表している)
[標準エラー出力の図]
[→] : 標準エラー出力

リダイレクションとパイプ

リダイレクション
標準入出力をファイルに切替える機能である。
例えば、ウインドウに出力されるデータをリダイレクションによってファイルに書き込んで 保存しておくことにより、いつでもそのデータを後で利用できるようになる。
% コマンド > ファイル
コマンドの標準出力をファイルに切替える
コマンドの出力がファイルに書き込まれる。
(標準エラー出力はファイルに書き込まれない。)
[標準出力へのリダイレクション]
% コマンド < ファイル
コマンドの標準入力をファイルに切替える
[標準入力からのリダイレクション]
% コマンド >& ファイル
標準出力・標準エラー出力の両方ともファイルに書き込む。
[標準エラー出力へのリダイレクション]
リダイレクションには上記以外にも いくつかの種類 がある。
なお、リダイレクションでファイルにコマンド出力を書き込む時、ファイルがすでに存在しているとファイルは上書きされて古い内容は消えてしまうので注意すること。
パイプ
あるコマンドの標準出力を他のコマンドの標準入力に切替える機能である。
パイプを使って2つ以上のコマンドを組み合わせることによって今まで存在しなかった機能を簡単に実現することができる。
% コマンド1 | コマンド2
コマンド1の標準出力をコマンド2の標準入力に切替える
[標準出力からのパイプ]
% コマンド1 |& コマンド2
コマンド1の標準出力・標準エラー出力の両方ともコマンド2の標準入力へ切替える。
[標準出力・標準エラー出力からのパイプ]

パイプは二つ以上使うことによって3つ以上のコマンドを接続することができる。
また、リダイレクションとパイプは同時に使用できる。

例1 ( リダイレクション )

あるコマンド(この場合はecho)によって ウインドウに出力されるデータ(testという文字列) を リダイレクション( > )によってdataというファイルに書き込んでいる。

% cd unix         ← unix ディレクトリへ移動(すでに移動済みの場合は不要)
% mkdir stdio     ← テスト用にディレクトリを作成する
% cd stdio        ← テスト用ディレクトリへ移動
% echo test       echoは引数の文字列を標準出力に出力するコマンド
test
% echo test > data1       ← その出力をdata1という名前のファイルに書き込む
% cat data1       ← data1の中身を出力すると
test              echoの出力が書き込まれている
% cat             catだけで実行
I am a boy        ← 入力が標準入力(キーボード)になる
I am a boy        ← 出力が標準出力に出力される
Ctrl+d            Ctrl+dで入力終り
%

例2 (標準エラー出力)

標準エラー出力に出力するコマンドの例としてlsを取り上げてみる。
lsのエラーメッセージは標準エラー出力へ出力される。
以下の例でlsのエラーメッセージが>>&によってどのようになるか、その出力先がどう変るかを見て欲しい。

% ls
data1                                   lsの出力は標準出力へ出力される
% ls > data2                            lsの出力をファイル(data2)に書き込む
% cat data2                             ← data2の内容を標準出力へ出力する
data1 data2                             lsの出力が書き込まれている
% ls data4                              ← 存在しないファイル(data4)を引数に与えると
ls: data4: No such file or directory    ← ファイル(data4)が無いというエラーメッセージがでる
% ls data4 > data3                      ← リダイレクションを使っても
ls: data4: No such file or directory    ← エラーメッセージが出力される
% cat data3                             ← data3には何も書き込まれていない
% ls data4 >& data3                     ← 今度は何も出力されない
% cat data3
ls: data4: No such file or directory    ← data3にエラーメッセージが書き込まれている
%

例3 ( パイプ )

例えば、あるディレクトリの中にあるファイルの個数を数えたいと思った時、どのようにすれば良いだろうか。
lsコマンドにはファイルの個数を数える機能はないし、そのようなことができる他のコマンドは存在しない。
しかし無ければ作れば良いだけの話である。
ここで、いきなりC言語などでプログラムを作ろうとは思わないで、まずコマンドの組合せで実行できないかを考えてみる。
考え方は以下のようになるだろう。

  1. まず、ファイルの名前を出力させる。 (もちろんlsを使う)
  2. その出力を単語を数えるコマンドの入力として与える。
    (ひとつのファイル名を、英単語ひとつとして数える)

データの単語数を数えてくれるコマンドにはwcというコマンドがあるので利用しよう。
この互いに関係の無い2つのコマンド(ここではlswc)をパイプ( | )で組み合わせることによって今まで存在しなかった機能(ファイルの個数を数える)が実現できる。

% ls             lsはファイル名を標準出力に出力する
data1 data2 data3
% wc data3       wcは引数にファイル名があるとそのファイルの行数・単語数・文字数を標準出力に出力する
      1       7      37 data3    ← data3は1行、単語7個、文字数37(スペース、改行を含む)
% wc -w data1    ← オプションに-wをつけると単語数だけ出力する
7 data3          ← data3の単語数は7
% wc             wcだけで実行する
This is a pen    ← 入力がキーボード(標準入力)になる
Ctrl+d           Ctrl+dで入力終り
      1       4      14          This is a penの行数1、単語数4、文字数14
% ls | wc -w     ← lsコマンドの出力結果をパイプを通してwcコマンドへ送る
 3               ← ファイルの個数
%
[例 3 の図]

上の例におけるls | wc -wというコマンドは以下のようにリダイレクションでも実現できる。
しかし、パイプを使用した方が一時ファイル(tmp)を作らないで済むし、実行効率も良い。

% ls > tmp       ← lsコマンドの出力結果をtmpに書き込む
% wc -w < tmp    ← tmpからデータを読み込む
 3               ← ファイルの個数

練習課題

参考


Prev | Next
Home | Contents
abe@injapan.net