まず予備知識ですが、Unix系OS (Linuxなど) の場合、コマンドラインでのデータの入出力先は「ファイルディスクリプタ」(「ファイル記述子」とも言う) というもので管理されます。これは整数で、入出力先がコンソールであろうとファイルであろうとそれぞれに固有のファイルディスクリプタが与えられます。
特に標準入力、標準出力、標準エラー出力は特別で、最初はそれぞれ0
、1
、2
というファイルディスクリプタが与えられることに決まっています。
さて、bashのマニュアルを読むと、(...)
は次のように説明されています。
(list)
list is executed in a subshell environment (中略). Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes. The return status is the exit status of list.
(...)
の中のコマンドのリストはサブシェル環境で実行されるとのことです。したがって
(ea "error" 2>&1) > a.txt
この場合、まず「ea "error" 2>&1」がサブシェルで実行されます。これはeaコマンドを実行する前に標準エラー出力を標準出力にリダイレクト (ファイルディスクリプタ2
を1
に向け変える) しています。従って、サブシェル内でのコマンド実行 (の失敗) によってファイルディスクリプタ1
にエラーメッセージが出力されます。
しかし、メインシェルの側では標準出力をファイルにリダイレクト (ファイルディスクリプタ1
を出力先のファイルディスクリプタに向け変える) しています。
結果として、エラーメッセージの出力はファイルに向かい、画面には何も出力されません。
いっぽう、
この場合、eaを実行する前に標準エラー出力を標準出力にリダイレクト (ファイルディスクリプタ2
を1
に向け変える) しています。それだけでなく、実行前には標準出力もファイルにリダイレクト (ファイルディスクリプタ1
を出力先のファイルディスクリプタに向け変える) しています。
つまり、eaを実行する前に
- 標準エラー出力はファイルディスクリプタ1 (元の標準出力) へ
- 標準出力はファイルへ
と向け変えられているわけです。
結果として、エラーメッセージの出力は画面へ向かい、ファイルには何も出力されません。
さらに、こういうこともできます。
この場合、eaを実行する前に標準エラー出力をファイルにリダイレクト (ファイルディスクリプタ1
を出力先のファイルディスクリプタに向け変える) しています。それだけでなく、実行前には標準エラー出力も標準出力にリダイレクト (ファイルディスクリプタ2
を1
に向け変える) しています。
つまり、eaを実行する前に
- 標準出力はファイルへ
- 標準エラー出力はファイルディスクリプタ1が向け変わったファイルへ
と向け変えられます。
結果として、エラーメッセージの出力はファイルへ向かい、画面には何も出力されません。また、仮にeaの実行が成功して標準出力にも何か出力されていたとしても、それもやっぱりファイルに書き込まれます。