紛らわしいけど重大な違いを引き起こすリダイレクト
何事もそうなのだけど、一文字違ったとか、順序が逆だったとかで予想とはだいぶ違う結果になってしまうことって、よくある。コマンドも然り。
$ echo ABC >& /dev/null #......1 $ echo ABC &> /dev/null #......2 $ echo ABC >/dev/null 2>&1 #...3 $ echo ABC >/dev/null 2&>1 #...4 $ echo ABC 2>&1 >/dev/null #...5 $ echo ABC 2&>1 >/dev/null #...6
検証
2
$ echo ABC &> /dev/null # 間違いと思われたが、なんとbashは「&>」も「>&」と解釈して処理しているようだ。 # つまり、正解!(しかし、好ましくはないと思う) $ echo ABC &> file $ cat file ABC $ _echo ABC &> file $ cat file –bash: _echo: command not found
3
$ echo ABC >/dev/null 2>&1 # 正解!(sh, bash 系の書き方)
4
$ echo ABC >/dev/null 2&>1 $ cat 1 ABC 2 $ _echo ABC >/dev/null 2&>1 $ cat 1 –bash: _echo: command not found # 標準出力・標準エラー出力とも、「1」という名前のファイルに保存される。 # 処理結果から以下のコマンドと同等な解釈のようだ。 $ echo ’ABC 2’ >/dev/null &> 1
リダイレクトの復習
# 何も指定しなければ、コマンドを実行した結果は、画面に出力される。 $ echo ABC ABC # エラーも画面に出力される。 $ _echo ABC -bash: _echo: command not found
# ファイルに出力したい時は「>ファイルパス」で指定する。 $ echo ABC >file $ cat file ABC #「>>ファイルパス」とすれば、上書きではなく、追記になる。 $ echo ABC >>file $ cat file ABC ABC # 「>ファイルパス」なら上書きになる。 $ echo ABC >file $ cat file ABC
# ところが、エラーはファイルに出力されず、未だ画面に出力される。 $ _echo ABC >file -bash: _echo: command not found # エラーが発生すると、正常な実行結果は存在しないので、ファイルの中身も消えた。 $ cat file
# エラー結果をファイルに出力するには「2>ファイルパス」で指定する。 $ _echo ABC 2>file $ cat file -bash: _echo: command not found # しかし今度は、正常な実行結果が画面に出力されてしまう。 $ echo ABC 2>file ABC # エラーが発生してないので、ファイルの中身も消えた。 $ cat file
- つまり、コマンドの正常な実行結果と、エラーとなった結果は区別されているのだ。
- 正常な実行結果は「標準出力」と呼ばれている。
- エラーとなった結果は「標準エラー出力」と呼ばれている。
- 「2>file」とは、標準エラー出力に file を指定したことになる。
- 「1>file」とは、標準出力に file を指定したことになる。
- つまり、標準出力・標準エラー出力ともにfileに出力したい場合は、両方のファイルディスクプリタを指定する必要があるのだ。
$ echo ABC 1>file 2>file $ cat file ABC $ _echo ABC 1>file 2>file $ cat file -bash: _echo: command not found
- ところで、fileの部分は長いパス名になることはよくあること。
- その長いパス名を2度入力するのは、苦痛である。
- そこで、「2>&1」という書き方がある。
- 「&1」はこの時点での標準出力の出力先を意味する。
- ちなみに「&2」ならこの時点での標準エラー出力の出力先を意味する。
- つまり、コマンドは左から順に解釈されるので...
- ちなみに、順序が逆になると...
$ echo ABC 1>file 2>&1 $ cat file ABC $ _echo ABC 1>file 2>&1 $ cat file -bash: _echo: command not found
- ところで、標準出力「1>」の1は省略することが許されているので...
$ echo ABC >/dev/null 2>&1 $ _echo ABC >/dev/null 2>&1
これで、すべての結果が破棄されるようになった!
- ちなみに、もし「2>&1」の書き方に自信がなくなったら、以下の書き方でもまったく問題ないのだ。
$ echo ABC 1>/dev/null 2>/dev/null
参考ページ
以下のページがたいへん参考になりました。感謝です!