リダイレクトはコマンドのファイル記述子を変更する機能です。リダイレクトを使用すると、コマンドの標準入力や標準出力を通常とは異なるファイルに繋ぎ換えた状態でコマンドを実行することができます。
リダイレクトはコマンド (単純コマンドまたは複合コマンド) にリダイレクト演算子を付することで行います。単純コマンドでは (他のトークンとくっつかない限り) どこでもリダイレクト演算子を置くことができます。複合コマンドではコマンドの最後にリダイレクト演算子を付けます。
リダイレクトはコマンドの実行が始まる前に処理されます。一つのコマンドに複数のリダイレクトがある場合は、リダイレクト演算子が書いてある順序で処理されます。オペランドなしの exec 組込みコマンドを実行する場合を除き、リダイレクトは対象となっているコマンドに対してのみ働きます。すなわち、対象のコマンドの実行が終わるとリダイレクトによって変更されたファイル記述子は元の状態に戻ります。
リダイレクト演算子は、<
または >
で始まります。<
で始まるリダイレクト演算子はデフォルトでは標準入力 (ファイル記述子 0) に作用します。>
で始まるリダイレクト演算子はデフォルトでは標準出力 (ファイル記述子 1) に作用します。どちらの種類の演算子でも、演算子の直前に非負整数を指定することでデフォルト以外のファイル記述子に作用させることができます (このとき整数と演算子との間に一切空白などを入れてはいけません。また整数をクォートしてもいけません)。
ファイルへのリダイレクト
最もよく使われるリダイレクトは、ファイルへのリダイレクトです。
- 入力のリダイレクト
-
< トークン
- 出力のリダイレクト
-
> トークン
>| トークン
>> トークン
- 入出力のリダイレクト
-
<> トークン
リダイレクトに含まれるトークンは四種展開されます。対話シェルではさらにパス名展開も行われます (パス名展開の結果が一つのファイルでなければエラーです)。トークンの展開結果がリダイレクト対象のファイル名として使われます。
入力のリダイレクトでは標準入力が対象ファイルからの読み込み専用ファイル記述子に置き換えられます。対象ファイルを開くことができなければエラーになります。
出力のリダイレクトでは標準出力が対象ファイルへの書き込み専用ファイル記述子に置き換えられます。対象ファイルが存在しなければ空の通常ファイルが作成されます。対象ファイルが既にある場合はそのファイルが開かれます。ただし演算子の種類によって以下のように挙動が異なります。
-
演算子
>|
では、対象ファイルが存在しそれが通常のファイルの場合、ファイルを開く際にファイルの内容を空にします。 -
演算子
>
は、clobber オプションが有効ならば演算子>|
と同じです。しかし clobber オプションが無効ならば、対象ファイルが存在しそれが通常のファイルの場合、エラーになります。 -
演算子
>>
では、ファイルを追記モードで開きます。ファイルへの書き込みは常にファイルの末尾へ追記する形で行われます。
入出力のリダイレクトでは標準入力が対象ファイルへの読み書き両用ファイル記述子に置き換えられます。対象ファイルが存在しなければ空の通常ファイルが作成されます。
ソケットリダイレクト
ファイルのリダイレクトにおいて、対象ファイル名が /dev/tcp/ホスト名/ポート
または /dev/udp/ホスト名/ポート
の形式をしていて、そのファイルを開くことができない場合、ファイル名に含まれるホスト名とポートに対して通信を行うためのソケットが開かれます。
/dev/tcp/ホスト名/ポート
が対象の場合はストリーム通信ソケットを、/dev/udp/ホスト名/ポート
が対象の場合はデータグラム通信ソケットを開きます。典型的には、前者は TCP を、後者は UDP をプロトコルとして使用します。
ソケットリダイレクトはどのリダイレクト演算子を使っているかにかかわらず常に読み書き両用のファイル記述子を開きます。
ソケットリダイレクトは POSIX 規格にはない yash の独自拡張です。ただし、bash にも同様の機能があります。
ファイル記述子の複製
ファイル記述子の複製のリダイレクトでは、既存のファイル記述子をコピーしたり閉じたりできます。
- ファイル記述子の複製
-
<& トークン
>& トークン
トークンはファイルのリダイレクトの場合と同様に展開されますが、これはファイル名ではなくファイル記述子として解釈されます。すなわち、トークンの展開結果はファイル記述子を表す非負整数となる必要があります。
演算子 <&
はトークンの展開結果で示されたファイル記述子を標準入力に複製します。演算子 >&
はトークンの展開結果で示されたファイル記述子を標準出力に複製します。演算子の直前に非負整数を指定することで、複製先のファイル記述子を変更できます。
トークンの展開結果が非負整数ではなくハイフン (-
) となった場合は、ファイル記述子を複製する代わりに閉じます。演算子 <&
では標準入力が、演算子 >&
では標準出力がデフォルトで閉じられますが、演算子の直前に非負整数を指定することで、閉じるファイル記述子を変更できます。
POSIX 準拠モードでは、<&
で複製するファイル記述子は読み込み可能でなければならず、>&
で複製するファイル記述子は書き込み可能でなければなりません。
ヒアドキュメントとヒアストリング
ヒアドキュメント・ヒアストリングを使うとコマンドに直接テキストを渡すことができます。
- ヒアドキュメント
-
<< トークン
<<- トークン
- ヒアストリング
-
<<< トークン
ヒアドキュメント・ヒアストリングでは、標準入力がヒアドキュメント・ヒアストリングの内容を読み込み可能なファイル記述子に置き換えられます。
ヒアドキュメント演算子 (<<
または <<-
) がコマンド中に現れると、その演算子のある行の次の行からはヒアドキュメントの内容とみなされます。ヒアドキュメントの内容の部分は、シェルのコマンドとしては解釈されません。演算子の後にあるトークンはヒアドキュメントの内容の終わりを表します。(トークンでは展開は行われませんが、クォートは認識されます。) 演算子のある行より後の行でトークンだけからなる行が現れた時点でヒアドキュメントの内容は終わりだと判断されます。終わりを表す行はヒアドキュメントの内容には含まれません。演算子 <<-
を使っている場合は、ヒアドキュメントの内容の各行頭にあるタブはすべて削除されます。このときトークンの前にタブがあっても (その行に他の余計な文字がなければ) ヒアドキュメントの内容の終わりとして認識します。
一行のコマンドに複数のリダイレクト演算子がある場合は、リダイレクトの内容は順番に処理されます。すなわち、その行の次の行からは最初のリダイレクトの内容として扱われ、その内容が終わったら、その次の行からは次のリダイレクトの内容として扱われます。最後のリダイレクトの内容が終わったら、その次の行からは再びコマンドとして解釈されます。
リダイレクトの内容は基本的に単なる文字列として扱われます。内容に含まれる空白やタブ、その他の記号はそのままコマンドに渡されます。ただし、トークンが全くクォートされていない場合は、ヒアドキュメントの内容はパラメータ展開・コマンド置換・数式展開され、$
, `
, "
, \
の直前にある場合および行の連結を行う場合にのみバックスラッシュを引用符として扱えます。
ヒアストリングでは、演算子の後にあるトークンはファイルのリダイレクトの場合と同様に展開されます。この展開結果がヒアストリングの内容となります。ただしヒアストリングの内容の末尾には自動的に改行が付きます。
ヒアストリングは POSIX 規格にはない yash の独自拡張ですが、bash, ksh, zsh にも同様の機能があります。
パイプリダイレクト
パイプリダイレクトを用いるとプロセス間通信に利用可能なパイプを開くことができます。
- パイプリダイレクト
-
>>| トークン
トークンはファイルのリダイレクトの場合と同様に展開されますが、これはファイル名ではなくファイル記述子として解釈されます。すなわち、トークンの展開結果はファイル記述子を表す非負整数となる必要があります。
パイプリダイレクトはパイプを開きます。標準出力 (演算子 >>|
の直前に非負整数を指定している場合はその値のファイル記述子) がパイプに書きこむためのファイル記述子になります。またトークンの展開結果で示されたファイル記述子がパイプから読み込むためのファイル記述子になります。
パイプリダイレクトは POSIX 規格にはない yash の独自拡張です。
プロセスリダイレクト
プロセスリダイレクトを用いると別のコマンドの入力または出力を受け渡せるパイプを開くことができます。
- プロセスリダイレクト
-
<(サブコマンド…)
>(サブコマンド…)
プロセスリダイレクトでは、サブコマンドがサブシェルで実行されます。このとき、<(サブコマンド…)
の形式のプロセスリダイレクトでは、サブコマンドの標準出力がこのコマンドの標準入力に渡るようパイプが開かれます。>(サブコマンド…)
の形式のプロセスリダイレクトでは、このコマンドの標準出力がサブコマンドの標準入力に渡るようパイプが開かれます。
プロセスリダイレクトは POSIX 規格にはない yash の独自拡張です。Bash と zsh にはプロセスリダイレクトと同様の構文を用いるプロセス置換という機能がありますが、プロセスリダイレクトとプロセス置換の挙動は異なっており、互換性はありません。