| author | プレハブ小屋 <2386769+showa-yojyo@users.noreply.github.com> | |||
|---|---|---|---|---|
| created | 2026-08-02 | |||
| draft | true | |||
| modified | 2026-08-03 | |||
| tags |
|
|||
| title | Bash redirections ノート |
ファイルを表すのに、ファイル名ではなく番号を使う場合がある。その番号をファイル記述子と呼ぶ。
Redirection において、Bash は下のファイル名を特別に扱う:
| ファイル名 | ファイル |
|---|---|
/dev/fd/fd |
ファイル記述子 fd に同じ |
/dev/stdin |
ファイル記述子 0 に同じ |
/dev/stdout |
ファイル記述子 1 に同じ |
/dev/stderr |
ファイル記述子 2 に同じ |
/dev/tcp/host/port |
対応 TCP ソケットを開こうとする †1 |
/dev/udp/host/port |
対応 UDP ソケットを開こうとする †1 |
†1: host は有効なホスト名か Internet 所在地であり、port はポート番号かサービス名とする。
このすべての構文において n は省いてもよい。そのときは 0, つまり標準入力が指定されたとみなされる。
| 構文 | 意味 |
|---|---|
n<word |
word を展開して得られる名前のファイルから入力する |
n<&word |
入力ファイル記述子 word を複製して n で使えるようにする |
n<&digit- |
入力ファイル記述子 digit を n に移転する |
n<<word |
here document の始まり |
n<<-word |
here document の始まり(タブ文字によるインデント可) |
n<<<word |
here string |
紙幅の都合上、here document/string は本稿では取り扱わない。
このすべての構文において n は省いてもよい。そのときは 1, つまり標準出力が指定されたとみなされる。
語 word に対応するファイルが実行直前に存在しない場合、Bash はそのファイルをまず作成する。
| 構文 | 意味 |
|---|---|
n>word |
記述子 n への出力をファイル word に向け直す †2 |
n>|word |
†2 |
n>>word |
記述子 n への出力をファイル word の末尾に出力する |
>&word |
†3 |
&>word |
1>word 2>&1 と同値 †3 |
&>>word |
1>>word 2>&1 と同値 |
n>&word |
出力ファイル記述子 word を複製して n で使えるようにする |
n>&digit- |
出力ファイル記述子 digit を n に移転する |
†2: この二つは実行直前に word が存在する場合の挙動が異なる。縦棒なしの記法では
set -o noclobber である場合にエラーとなる。
†3: この二つは基本的に同じ意味だが、構文 >&word では語が番号や - に展開されることは許されない(構文 n>&word と解釈される)。
記法 n<>word はファイル word を、入力と出力のどちらもファイル拡張子 n により実現できるようにする。
ファイル記述子 0, 1, 2 以外のものを利用する場合、未使用のものを自分で探すのは危険だ。
構文 {var}<fd, {var}>fd, etc. を用いると、Bash が操作者に代わって新しいファイル記述子を見つくろい使用可能にし、変数 var に割り当てる。
また、shopt -s varredir_close である場合、命令の実行完了時に {var}<fd 構文を用いて割り当てられたファイル記述子は Bash が閉じる。
Tip
当然 shopt -s varredir_close しておくべきだろう。
Bash Reference Manual から例を引く:
ls > dirlist 2>&1> dirlistは1>dirlistの意味だから、標準出力への出力をファイルdirlistに向け直す。2>&1は標準出力を複製して標準エラーで使えるようにする。
実行直後、ファイル dirlist の内容が標準出力と標準エラーへの出力に、発生順に書き出されていることが期待される。
Bash では演算子 &> も使えるということを知らないとマズい:
ls &>dirlist次の命令は標準出力しかファイルに書き出さない:
ls 2>&1 > dirlist2>&1は標準エラーを標準出力の複製として扱う。> dirlistは標準出力をファイルdirlistに向け直す。
$ exec 3<> /tmp/foo
$ echo "test" >&3
$ cat /tmp/foo
test
$ exec 3>&-
$ echo "test" >&3
-bash: 3: Bad file descriptor- ファイル記述子を「開いて」「閉じる」には
execを用いる。 - 同時に複数のファイル記述子を開くことが可能であることに注意。面白い何かが実現するかもしれない。
Bash Reference Manual にわずかに記載があるように、構文 {varname}redirecion を用いてもいい:
$ exec {var}>|/tmp/foo
$ echo test >|{var}
$ cat <{var}
test
$ ls /dev/fd/${var}
/dev/fd/10
$ exec {var}>&-
$ ls /dev/fd/${var}
ls: cannot access '/dev/fd/10': No such file or directory番号 n を(自分で開いた)ファイル記述子とする。手動でこれを閉じるには exec n>&- と exec n<&- のどちらでも有効だ。
Redirection の機能はファイルハンドルを操作することで、命令の入出力対象を変更することだと考えられる。
- 組み込み命令
execを用いる場合、redirection は現在のシェル実行環境内のファイルハンドルを変更する。 - Redirection 演算子は単一命令の(先頭、途中、末尾の)どこにでも書ける。
- Redirection は出現順に、左から右へと処理される。Redirection の順序は重要だ。
- 上の各表で n が付けられる redirection は、
{varname}形式の語を代わりに先頭に付けることも可能。 - ファイル記述子は
10以上の番号になり、それを{varname}に割り当てる。 >&-or<&-の先頭にある場合、値{varname}により閉じられるファイル記述子が定義される。- 命令の有効範囲を超えて生き残るファイル記述子を、使用者が手動で(移転構文で)管理しろ。
上の各表における演算子直後の word は、基本的には各種展開(中括弧展開や変数展開など)の対象となる。複数の語に展開される場合、エラーとなる。
- ファイルを開くか作成できない場合、redirection は失敗する。
- 少なくとも
{varname}redir 構文を用いないと、番号が9より大きいファイル記述子はシェルが内部で使用するものと衝突する可能性がある。
以上