注意!!!
こちらの記事には、多分に誤りがあります。
修正後のページをご確認ください。
せっかくコメントを頂けましたし、自分がどう勘違いしていたかを覚えておくため、
黒歴史として敢えて残しておきます。
はじめに
「Linuxでコマンドをぶったたいてる時どっちが先だっけ?と迷うヤツ選手権」を開いたら、
恐らく、tarか/dev/nullリダイレクションが優勝すると思います。
ということで、今回は優勝候補の/dev/nullリダイレクションさんについて調べてみます。
順番間違ってても一見行けそうじゃん?と思うけど、実際はいけないんですよね。
そもそもリダイレクションとか1とか2って何
…の前に、まずは標準出力と標準エラー出力について。
標準出力とは、プログラムのデータの出力先です。通常はディスプレイが出力先です。
標準エラー出力は、エラーメッセージ等に用いられます。こちらも通常はディスプレイが出力先です。
で、1は標準出力、2は標準エラー出力を指すファイルディスクリプタです。
ファイルディスクリプタというのは、OSが標準出力とかを認識するためのIDです。
...ややこいですね。
要するに、lsとかのコマンドをぶったたいた時、lsはコマンドの出力結果を
ディスプレイにぶっ飛ばそうとします。
正常終了した結果なので、1(最初は標準出力を指す)に飛ばします。
lsの引数に指定したファイルが見当たらないときは「見当たらん!」という
メッセージを、ディスプレイにぶっ飛ばそうとします。
これはエラーメッセージなので2(最初は標準エラー出力を指す)に飛ばします。
イメージ的にはこんな感じです。
そのぶっ飛ばし先を変更するのがリダイレクションです。
あと、/dev/nullは書かれたデータを全部捨てるスペシャルファイルというものです。
ここにぶっ飛ばされたデータは出力されることなく海のもずくになります。
正しいほう(1>/dev/null 2>&1)の動作
とにかくディスプレイに何も出力させたくない!全部出力を捨てる!
という時に上記のリダイレクションを使います。
これはすなわち、以下のような感じです。
まず、1の出力先を標準出力から/dev/nullに切り替えて
次に、2の出力先を1の出力先(=/dev/null)に切り替えます。
これで、両方の出力を無事に捨てることができるわけです。
1というのが、所詮ポインタであって、イコール標準出力ではない、というところがミソです。
だめなほう(2>&1 1>/dev/null)
ありがちな間違いのほうです。
…なんということでしょう。エラーメッセージが標準出力に残っちまいました。
1イコール標準出力と勘違いしていると、まず標準エラー出力を標準出力とまとめて、
そのまとまった標準出力をまとめてポイ出来ると思っちゃいますよね。
実証
正しいほうで、存在するファイルとしないファイルをlsしてみます。
# ls
dada
# ls dada mama 1>/dev/null 2>&1
#
ばっちりですね。次、だめなほう。
# ls dada mama 2>&1 1>/dev/null
ls: mama にアクセスできません: そのようなファイルやディレクトリはありません
#
…これだと標準出力なのか標準エラー出力なのかわからないので、もう一ひねりします。
|(パイプ)は通常、標準出力しか受け取りませんので、それを利用してどっちで出力されてるか判断します。
(蛇足ですが、|&とすると、標準エラー出力も受け取るようになります)
もしgrep mamaをして表示されれば標準出力、表示されなければ標準エラー出力です。
# ls dada mama 2>&1 1>/dev/null | grep mama
ls: mama にアクセスできません: そのようなファイルやディレクトリはありません
#
標準出力でした。
〆
こういった、一見よくわからない記載というのは、
「もう意味とかいいからそのまんま覚えろ!おまじない!」
とよく言われますが、私はおまじないとか言ってはぐらかすのは嫌いなんです。
やっぱり、意味をしっかり理解した上で納得して使わないとね。
…そういう性格のおかげで、調べるのにやたら時間かかったりしますが(笑)