Linux講座にようこそ。このページは「Linuxの使い方 - 第2章 シェルの基本機能」です。

Linuxの使い方

2. シェルの基本機能(2/2)

2.2 リダイレクション(入出力の切替え)

標準入出力
【図2-2】標準入出力

シェルは入出力先として、標準入力標準出力標準エラー出力の3種類を持っており、これを標準入出力と呼んでいます。標準入出力ではデフォルトの入出力先として、標準入力はキーボード、標準出力はターミナル、標準エラー出力もターミナルと決まっています。(従って、ターミナルにコマンドの出力結果とエラーメッセージが一緒に出力されます)

リダイレクションは、これらのデフォルトの入出力先を別の入出力先に変更する機能です。

2.2.1 一般形式

入出力先を切替えるための記号と使い方は次の通りです。(これらの記号の前後に空白文字が有っても無くても構いません)

$ コマンド < ファイル名
$ コマンド > ファイル名
$ コマンド >> ファイル名
$ コマンド &> ファイル名
$ コマンド 2> ファイル名
<
標準入力を切替えるための記号です。ただし、ほとんどのコマンドは引数に入力ファイルを指定できるようになっているため、この記号を使って切替えることは少ないでしょう。
>
標準出力を切替えるための記号です。指定したファイルが存在しないときは新規に作成し、存在したときには上書きになります。
>>
標準出力を切替えるための記号です。指定したファイルが存在しない場合は新規に作成しますが、存在したときには追加書きになります。
&>
標準出力と標準エラー出力を切替えるための記号です。コマンド実行時に表示されたエラーメッセージをファイルに保存したいようなときに使います。
2>
標準エラー出力を切替えるための記号です。エラーメッセージだけをファイルに保存したいようなときに使います。

2.2.2 実行例

ここで使用しているcatコマンドは、標準入力から入力して標準出力に出力します。引数に入力ファイルを指定できますので、テキストファイルの内容を見たいときによく使います。(catコマンドの詳細は「テキストファイルの連結(catコマンド)」をご覧ください)

catコマンドで/etc/issueファイルの内容を2つの方法で出力(標準出力)します。ファイルの指定方法は異なりますが結果は同じです。

$ cat < /etc/issue ← <で標準入力を/etc/issueに切り替えます
Fedora release 16 (Verne)
Kernel \r on an \m (\l)

$ cat /etc/issue ← 引数に/etc/issueを指定します(こちらの方法で実行するほうが多いと思います)
Fedora release 16 (Verne)
Kernel \r on an \m (\l)

$

簡単な内容のテキストファイルを作ります。(内容は「Hello World」の1行のみです)

$ cat > file1.txt
Hello World ← キーボード入力待ちの状態になるので1行入力(最後はEnterキー)します
← ここで、CtrlとDキーを同時に押します(E.O.Fの入力)
$
$ cat file1.txt ← file1.txtファイルの内容を表示します
Hello World
$

dateコマンドの出力(標準出力)結果をファイルに出力します。(ファイルの内容はcatコマンドで表示して確認します)

$ date "+%c"
2000年12月24日 19時47分03秒 ← 出力の切替えを行っていないのでターミナルに出力します
$ date "+%c" > file2.txt
$ cat file2.txt ← 結果を確認します
2000年12月24日 19時48分34秒
$ date "+%c" >> file2.txt ← 追加出力を指定します
$ cat file2.txt ← 結果を確認します
2000年12月24日 19時48分34秒
2000年12月24日 19時49分51秒
$

findコマンドでHello.cファイルを検索して、エラーメッセージ(標準エラー出力)をファイルに出力します。(findコマンドの詳細は「4.3.5 ファイルの検索(findコマンド)」をご覧ください)

$ find . -name "Hello.c"
find: ‘./TMP/WORK’: Permission denied ← エラーメッセージです
./MYHOMEPAGE/SEMICMD/EXSAMPLE/BACKUP/Hello.c ← 検索結果です
./MYHOMEPAGE/C_LANG/Hello.c ← 検索結果です
$
$ find . -name "Hello.c" &> err.txt ← 標準出力と標準エラー出力を切替えます
$
$ cat err.txt ← 結果を確認します
find: ‘./TMP/WORK’: Permission denied
./MYHOMEPAGE/SEMICMD/EXSAMPLE/BACKUP/Hello.c
./MYHOMEPAGE/C_LANG/Hello.c
$
$ find . -name "Hello.c" 2> err.txt ← 標準エラー出力だけを切替えます
./MYHOMEPAGE/SEMICMD/EXSAMPLE/BACKUP/Hello.c
./MYHOMEPAGE/C_LANG/Hello.c
$
$ cat err.txt
find: ‘./TMP/WORK’: Permission denied ← エラーメッセージ(標準エラー出力)だけです
$

2.3 パイプライン

パイプライン
【図2-3】パイプライン
標準出力から出力して、標準入力から入力していきます

UNIX流の考え方に「単機能なコマンドを組み合わせて高度な作業を行なおう」ということがあり、これを実現する手段の一つがパイプラインです。

パイプラインでは前に指定したコマンドの実行結果が次のコマンドに渡って行きます。このとき、前のコマンドの標準出力が次のコマンドの標準入力に渡ります。従って、パイプラインの途中のコマンドは標準入力と標準出力の両方を持っている必要があります。パイプラインの途中で使えるコマンドをフィルタと呼んでおり、標準で提供されるコマンドの多くがフィルタです。

ファイルの内容を加工するような場合、通常は先頭のコマンドでファイルを入力します。そして、途中のコマンド(フィルタ)は標準入力・標準出力で入出力を行いますので、ファイルを指定する必要はありません。結果をファイルに保存する場合は、最後のコマンドで出力ファイルとして指定します。(多分、標準出力の切り替え(<または<<)を指定することが多いと思います)

パイプラインでは、それぞれのコマンドは並列的に実行しますし、標準入力・標準出力はメモリ間でデータの受け渡しを行いますので、コマンドを単独で実行するより効率的に作業を行えます。

2.3.1 一般形式

コマンドとコマンドの区切りに|(縦線)を使用します。(|の前後に空白文字が有っても無くても構いません)

$ コマンド1 | コマンド2 | コマンド3 …

2.3.2 実行例

lsコマンドの実行結果をlessコマンドに送って、lessコマンドで実行結果を確認します。

$ ls -l /usr/bin | less
(以降にlsコマンドの実行結果が表示されます)

date_list.txtファイルの日時情報を新しいものから古いものの順(降順)に並べ替えて、行番号を付加して表示します。並べ替えはsortコマンドに-rオプションを、行番号の付加はcatコマンドに-nオプションを指定します。

$ cat date_list.txt ← date_list.txtファイルの内容を表示します
2015年09月06日 09時29分07秒
2015年09月06日 09時58分26秒
2015年09月06日 10時00分48秒
2015年09月07日 08時49分18秒
2015年09月07日 09時18分37秒
$ 
$ sort -r date_list.txt | cat -n ← sortコマンドで降順に並べ替えて、catコマンドで行番号を付加して表示します
     1  2015年09月07日 09時18分37秒
     2  2015年09月07日 08時49分18秒
     3  2015年09月06日 10時00分48秒
     4  2015年09月06日 09時58分26秒
     5  2015年09月06日 09時29分07秒
$

2.4 その他の知っておくと便利な機能

ここではコマンドの実行の仕方で、上記以外で知っておくと便利な、次の方法をご紹介します。

  • 連続実行
  • バックグラウンド実行(バックグラウンドプロセス)
  • 実行結果の判別実行

連続実行はパイプラインと似ていますが、こちらは、ただ単に複数指定されたコマンドを順番に実行します。従って、複数のコマンドを1行で指定したいような時に使用します。

バックグラウンド実行(バックグラウンドプロセス)はマルチプロセスの機能を使って、並列的にコマンドを実行しますので、処理時間のかかるコマンドや永久的に実行するコマンドを実行するときに使用します。バックグラウンドプロセスを実行すると、すぐにプロンプトが表示されますので、次のコマンドを実行できます。

バックグラウンドプロセスに対して、今までのコマンド実行をフォアグラウンドプロセスと呼んでいます。フォアグラウンドプロセスの場合は、終了するまでプロンプトが表示されないため、次のコマンドは実行できません。(フォアグラウンドプロセスが終了するとプロンプトが表示されます)

実行結果の判別実行は直前のコマンドの終了条件(終了ステータス)により、実行するか否かを判定します。直前のコマンドが正常終了したときに実行する、或は、異常終了したときに実行するという制御が出来ます。なお、標準で提供されるコマンドは終了ステータスと呼ぶ値を設定しており、この値は正常終了したときは0、異常終了したときは0以外です。終了ステータスを調べるには、調べたいコマンドの実行直後に「echo $?」を実行します。

2.4.1 一般形式

連続実行は;記号、バックグラウンド実行は&記号、実行結果の判別実行は&&||を使用します。(これらの記号の前後に空白文字が有っても無くても構いません)

$ コマンド1 ; コマンド2 ; コマンド3 …
$ コマンド &
$ コマンド1 && コマンド2 ← コマンド1が正常終了したときにコマンド2を実行します
$ コマンド1 || コマンド2 ← コマンド1が異常終了したときにコマンド2を実行します

2.4.2 実行例

clearコマンドとdateコマンドを1行で指定します。

$ clear ; date "+%c"
(ターミナルがクリアされて、先頭行にdateコマンドの実行結果が表示されます)

xclock(時計のアプリケーション)をバックグラウンドで実行します。

$ xclock &
[1] 2993 ← ジョブ番号とプロセスIDが表示されます(詳細は「5.6 プロセスの操作」をご覧ください)
$ ← すぐにプロンプトが表示されますので、コマンドの実行が可能です

前のcatコマンドの実行結果により、dateコマンドを実行するか否かが決まります。

$ cat file2.txt && date "+%c" >> file2.txt
     ↑ catコマンドが正常終了したときのみ、dateコマンドを実行します
$ cat file2.txt || date "+%c" >> file2.txt
     ↑ catコマンドが異常終了したときのみ、dateコマンドを実行します

catコマンドの終了ステータスを表示します。

$ cat file2.txt
2000年12月24日 19時48分34秒
2000年12月24日 19時49分51秒
$ echo $?
0 ← 終了ステータスは0です(正常終了)
$ 
$ cat file2.txt ; echo $? ← 上記2つのコマンドを1行(連続実行)で指定します
2000年12月24日 19時48分34秒
2000年12月24日 19時49分51秒
0
$ 
$ cat file3.txt || echo $? ← catコマンドが異常終了した場合、echoコマンドを実行します
cat: file3.txt: そのようなファイルやディレクトリはありません
1 ← 終了ステータスは0以外です(異常終了)
$