Linuxのコマンドラインはただでさえ難解ですが、中でもとりわけ難解(少なくとも私にとっては)なのが、標準入出力・エラー出力のリダイレクトの構文です。
私にとってはこれもう、殆ど呪文でした。
これまで何度も、「忘れる → 調べる→ また忘れる。」を繰り返してきましたが、もう繰り返さないぞ!
というわけで、このテーマで投稿して(私用に)記録に残しておきます。
” リダイレクト ” という用語は、あるサイトに接続すると別のサイトに飛ばされる設定も ” リダイレクト ” と呼ばれますが、今回はその意味ではありません。
ファイルディスクリプタ値(FD値)
ファイルディスクリプタ値(FD値)は、「プロセスが開いたリソースを管理する数値」となっています。
何にことやらさっぱり分かりませんが取りあえずまずはそこは置いておいて、
この数値の0が標準入力、1が標準出力、2が標準エラー出力と定義されています。
ファイルディスクリプタ値 (FD値) | 意味 | デフォルト値 |
0 | 標準入力 | キーボード |
1 | 標準出力 | ディスプレイ |
2 | 標準エラー出力 | ディスプレイ |
普段はデフォルト値に設定されているので、コマンドはキーボードから入力し、結果やエラー表示はディスプレイから出力されます。
FD値は3以上の値の内容も設定できます。
標準入力・標準出力・標準エラー出力のリダイレクト
この0~2の数値の内容を変更すると、標準入力元or標準出力先or標準エラー出力先が変わります。
これを(標準入力or標準出力or標準エラー出力)のリダイレクトと呼びます。
数値そのものを変更するのでなく、数値は単なる格納倉庫の表札であり、その倉庫に格納されている内容が変更されます。(ここが大事)
FD値を倉庫に例えて(2段目)、表を再掲すると下表になります。
FD値 | 意味 | 格納されている デフォルトの内容 | リダイレクトによる変更 |
倉庫に例えると 倉庫番号 | 倉庫の目的 | 最初に倉庫に入っている物品 | 入替可能な物品 |
0 | 標準入力 | キーボード | 任意のファイルなどに変更可能 |
1 | 標準出力 | ディスプレイ | 任意のファイルなどに変更可能 |
2 | 標準エラー出力 | ディスプレイ | 任意のファイルなどに変更可能 |
3以降 | 未定 | 未設定 | 任意のファイルなどに変更可能 |
最も頻繁に行われるリダイレクトは入力元や出力先を、ファイルに変更することです。
なおFD値は、 ” < ” や ” > ” の直前直後に付ける数値です。(間にスペースを挟まずにくっついています。後述)
リダイレクトの実際
標準入力・標準出力・標準エラー出力の切替をリダイレクトと言います。
入力元をファイルに変更
コマンド < 入力元ファイル名
” < ” の前後にスペースが開いていることに留意
出力先をファイルに変更
コマンド > 出力先ファイル名
” > ” の前後にスペースが開いていることに留意
或いは、下記でも同じです。(むしろこちらが正式で、上記がその省略形。上記はそもそもデフォルトと同じ指定なので省略されている訳です)
コマンド 1> 出力先ファイル名
” FD値1 ” (標準出力先)を、出力ファイル名に変更、という意味です。
” 1 ” と ” > ” の間にスペースが無いことに留意! ← これが重要
エラー出力先をファイルに変更
コマンド 2> エラー出力先ファイル名
” FD値2 ” (標準エラー出力先)を、出力ファイル名に変更、という意味です。

上記の例では、存在しない ” xxx ” というディレクトリの内容を表示しようとしたせいでエラーが出たけど、そのエラーはディスプレイに表示されずに、 ” error.txt ” というファイルに書き込まれています。
” 2 ” と ” > ” の間にスペースが無いことに留意!
出力とエラー出力先を同じファイルに出力
以下の2つは同じ意味で、出力とエラー出力が同じファイルに書き出されます。
コマンド &> ファイル名

コマンド >& ファイル名

” & ” と ” > ” の間にスペースが無いことに留意!
上書きと追記
” > ” は上書きであり、これを ” >> ” に置き換えると追記にします。
下記はコマンド出力をファイルに上書き(既存ファイルの内容は消える)
コマンド > ファイル名
下記はコマンド出力をファイルに追記(既存ファイルの内容が残る)
コマンド >> ファイル名
難解な構文の解釈
下記構文はスクリプトなどに頻回に出てきますが、最初は全然意味が分かりませんでした。(よく出る構文はほぼこの1パターンだけです)
コマンド > ファイル名 2>&1

これは出力とエラー出力を両方とも同じファイルに書き込む構文です。
最初の ” > ” は前後にスペースあり、2つ目の ” > ” には前後にスペースが無いことに留意
つまり前述の ” &> ” や ” >& ” 構文と同機能の構文です。前述の方法が新しく、こちらは古い方法です。
参考)
参考までに ” > ” の前後にスペースを開けるとエラーになります。

解釈
コマンド再掲
コマンド > ファイル名 2>&1
まずこれ、どこに切れ目があるのかが一目では分かりません。最初はここから躓いて苦労してました。
これは以下の2つに分けて考えます。
- 前段の「コマンド > ファイル名」ではコマンドの出力をファイルに書き込みます
- 後段の「 2>&1 」でエラー出力も同じファイルに書き込みます
前段の意味はこれまでに説明した通りです。問題は後段です。
” 2>&1 ” はFD2の内容にFD1の内容をコピーして入れるという意味です。( ” & ” は複製するという意味)
前段の時点で、FD1の内容には ” ファイル名 ” が入っていますので(つまり標準出力がファイルに変わっているので)、後段で、FD2の内容もそれがコピーされて ” ファイル名 ” に変わります(なので標準エラー出力先も同じファイルに変わります。)
ゴミ箱に入れる
コマンド > /dev/null
” /dev/null ” がゴミ箱です。のでここに向けて出力すると破棄されます。
関連事項
リダイレクトの関連コマンドです。
2つのコマンドの接続
これは有名ですが、パイプ ” | ” を使います。
コマンド1 | コマンド2
コマンド1の結果をコマンド2に直接渡す。
枝分かれして両方向に出力
” tee ” コマンドを使います。(teeは ” T ” の意味=枝分かれの意味)
コマンド1 | tee ファイル1
コマンド1の結果を、ディスプレイにも出力し、ファイル1にも書き出す。
まとめ
今回は、私の個人的謎解き記事でした。
謎解きすると何という事はなさそうですが、これがスクリプトの途中とかに予告なく出てくると、いつも頭に???が湧いていました。
要は、
- FD値の「0・1・2」が、「標準入力・標準出力・標準エラー出力」に対応してる
- リダイレクト記号 ” > ” の直前と直後にFD値があって、前の内容に後の内容を代入する
- この構文は ” > ” の前後にスペースが無いことで発見する
ということです。
コメント