LoginSignup
119
79

More than 3 years have passed since last update.

リダイレクトとして 2&>1 を使うと何が起きるのか?

Last updated at Posted at 2017-12-14

はじめに

初心者の頃によく混乱した Bash の「標準エラー出力を標準出力に流す」記法 2>&1 についてです。
当時は意味もわからず間違って 2&>1 とかやってましたが、今改めてこの 2&>1 について挙動を確認してみます。

そもそも 2>&1 とは

  • 標準エラー出力 2 を 標準出力 1 と同じ設定にする (と覚えてます)
    • 結果、2つとも同じところ (標準出力) に出力される

叩いてみる

手っ取り早く標準エラー出力を出せる以下コマンド (?) を使います。

$ aaa
-bash: aaa: command not found

:thumbsup_tone1: 正しい方法 2>&1

# 標準出力をファイルに保存
$ aaa > /tmp/stdout_check.log 2>&1
$ cat /tmp/stdout_check.log
-bash: aaa: command not found

確かに標準エラー出力が標準出力と一緒にファイルへリダイレクトされています。

:thumbsdown_tone1: 間違った方法 2&>1

$ aaa > /tmp/stdout_check.log 2&>1
$ cat /tmp/stdout_check.log 
$

ファイルは空っぽ。
試しにファイルへのリダイレクトをなくしてみます。

$ aaa 2&>1
$

当然ながら何も出力されません。
ここでカレントディレクトリを見てみると

$ ls -l 1
-rw-r--r-- 1 togawa togawa 30 11月 24 13:57 1
$ cat 1
-bash: aaa: command not found

1 というファイルができています。どうやら 1 というファイルにリダイレクトされてしまったようです。

もう少し紐解いてみる

引数をとるコマンド grep で試す

$ echo test | grep test 2&>1
$ cat 1
grep: 2: No such file or directory

grep を使い test という文字列を検索してみます。
2: No such file or directory というエラーメッセージを得ました。
想定では標準入力が検索対象となるはずでしたが、実際は 2 というファイルを読み込もうとしていたようです。

ここで、上記コマンドをスペースで整形すると以下のようになります。

$ grep test 2 &>1

紐解くと

  • grep test 2: test という文字列を 2 というファイルから検索
  • &>1: 標準エラー出力と標準出力を 1 というファイルにリダイレクト
    • >1 2>&1 したのと同じ

となります。
つまり、2&>1 は「2 という引数」と「&>1 というリダイレクト」に分解されることになります。

aaa 2&>1 のときも、実は aaa2 という引数を与えていたのでした。

まとめ

  • 標準エラー出力を標準出力に流すための正しい書き方は 2>&1
  • 間違った書き方 2&>1 は「2 という引数」と「&>1 というリダイレクト」に分解される
    • 標準エラー/標準出力いずれも "1" というファイルに書き込まれてしまう
  • これに限らず、何事も丸暗記ではなくて根本から理解して使うと安全

参考

119
79
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
119
79