【UNIX】リダイレクトとパイプとは何か?

UNIXコマンドにおけるリダイレクトとパイプという言葉を聞いたことはあるでしょうか?
普段からコマンドラインの操作に慣れている方は、ご存知かもしれませんが、意外と知らない方も多いのではないでしょうか。
今回は、リダイレクトとパイプがどういうものなのか、これらがコマンドの操作でどう便利なのかについて説明していきます。
コマンドラインプログラムの概要
リダイレクトとパイプというのは、コマンドラインを便利に使えるようにするための機能ですが、そもそもコマンドラインがどんなものなのかを簡単に見ていきましょう。
プログラムには、入力、処理、出力という3つのステップがあり、処理はプログラム内で行われますが、入力と出力の部分にはプログラムと実行環境を繋ぎ受け渡しをするものが必要となります。
UNIXやUnix系のOSでは、このプログラムと実行環境のデータの受け渡しとして、標準入力 , 標準出力 , 標準エラー出力 という3つの入出力チャネルに分けられていて、この3つで構成されたものを標準ストリームと呼びます。
標準ストリームという言葉は馴染みがなくても、標準入力(stdin, standard input)、標準出力(stdout, standard output)という言葉は聞いたことがある人も多いんじゃないでしょうか。
ストリームというのはデータの流れを指していて、標準入力はプログラムに入ってくるデータ、標準出力はプログラムが書き出すデータ、標準エラー出力(stderr, standard error)はエラーメッセージを出力するためのストリームで、標準出力と分けることによって正しく実行された結果とエラーメッセージを分けることができます。
標準入力として思い浮かべるものとしてキーボードからの入力、標準出力として画面に表示される出力を思い浮かぶかもしれません。
これはデフォルトで、標準入力はキーボードからの入力、標準出力と標準エラー出力はコンソールに出力となっているだけで、入力元、出力先として、ファイルを指定したり、コマンドラインプログラムの実行結果をそのまま次のプログラムに流用したりすることもできます。
その標準ストリームの入出力先を変更できるのが、今回説明する リダイレクト と パイプ です。
リダイレクト
リダイレクトは、入力や出力を指定することができる機能です。
主に、実行結果をファイルに書き込んだり、ファイルの情報を読み込んだりすることに使えます。
リダイレクトを使うには>
と<
という不等号記号を矢印のように指定することで使えます。
標準出力の指定
コマンド > ファイル
: 標準出力をファイルに書き込む。ファイルが存在しない場合は新規作成。ファイルが存在していたら上書き。
コマンド >> ファイル
: 標準出力をファイルに追記する。
echo
という標準入力を標準出力に返すというコマンドを利用して、リダイレクトの使い方を見ていきます。
echo
コマンドのサンプル
$ echo "hogehoge"
hogehoge
それでは実際にファイルに出力します。
実行
# 「hello world」という文字が入ったファイルが作成されます。
echo "hello world" > hello.txt
# 「hello world」が「Good Morning」に置き換えられます。
echo "Good Morning" > hello.txt
標準入力の指定
先ほどは、リダイレクトを標準出力を変えるという使い方をしましたが、入力先を変えることもできます。
記号の向きを先ほどと逆にすると、標準入力を指定することができます。
コマンド < ファイル
: ファイルの内容を標準入力として受け取りコマンドを実行する。
bc
コマンドという計算の処理するコマンドを使って見ていきます。
以下のファイルを用意します。
calc.txt
10*5+6
実行
$ bc < calc.txt
56
正しく計算されました。
このようにリダイレクトは入出力先としてファイルを指定する時によく使われます。
実行結果をファイルとして残しておきたい時など、便利に使うことができます。
サンプル: コマンドの入力履歴ををファイルに出力
history > command.log
パイプ
パイプは、標準出力を次のコマンドの標準入力に受け渡しをすることができる機能です。
名前の通り、コマンドとコマンドを繋ぐパイプのような機能です。
コマンド1 | コマンド2
: コマンド1の標準出力をコマンド2の標準入力に渡して実行する。
find
コマンドでファイルを検索するコマンドと、wc
という文字数や行数を調べるコマンドをパイプで組み合わせて、該当するファイルがどれくらいあるかを調べます。
find . -type f -name "*.java"
は、カレントディレクトリ(.
)から、ディレクトリではなくファイルでかつ、ファイル名が.java
で終わるものを一覧で出力します。
wc -l
は、標準入力の行数を出力します。
実行
$ find . -type f -name "*.java" | wc -l
55
現在のディレクトリ以下にjavaファイルが55個あるのが分かりました。
このように、大量の出力結果を次のコマンドで使いたい時に便利に使うことができます。
パイプはgrep
などの検索系の処理や、sed
などの文字列処理と組み合わせるのによく使われます。
まとめ
以上がリダイレクトとパイプの説明となります。
UNIXの哲学として、プログラムを小さくして小さなまま保つというものがあります。
小さいプログラムは機能が明確で、保守もしやすく、組み合わせがしやすいという利点があるためです。
一つ一つのコマンドがシンプルで便利ですが、うまく組み合わせることでさらにコマンドラインが便利なものになるでしょう。
お読みいただきありがとうございました。