標準出力を捨てる方法

TL;DR

標準出力のみ捨てる

$ command > /dev/null

標準出力、標準エラーの両方を捨てる

$ command &> /dev/null    # bashの場合

もしくは、

$ command > /dev/null 2>&1

/dev/null

標準出力の簡単な捨て方は、UNIX系OSに標準である「ゴミ箱」に出力をリダイレクトすることです。

このゴミ箱は/dev/nullであり、ブラックホールと表現する方もいるそうです。むしろそっちの方がイメージ的には当たっていそうです。

/dev/null はスペシャルデバイスであり、ls コマンドを用いて確認することができます。ここに出力したデータはすべて破棄され、取り出すこともできません。プログラムやコマンドを実行したときに、ユーザにとって不要な出力を無視するために使われます。

標準出力を捨てる方法

例えば、以下のようにすることで標準出力を捨てることができます。

$ ls -l > /dev/null

しかし、以下のように標準エラーに関しては依然表示されます。

$ ls -l hoge > /dev/null
ls: cannot access 'hoge': No such file or directory

これを理解する為には、ファイルディスクリプタについて考える必要があります。

ファイルディスクリプタ(fd)

簡単に言うと、ファイルディスクリプタとはプロセスが、標準入出力やその他操作するファイルを識別するための番号のようなものです。ここらへんの詳細な仕組みは私も厳密にはわかりません…いずれしっかり理解してまとめたいな…

このファイルディスクリプタの既定値は以下のようになっています。

  • fd 0 : 標準入力(stdin)
  • fd 1 : 標準出力(stdout)
  • fd 2 : 標準エラー出力(stderr)

この3つのファイルディスクリプタがプロセス開始時に準備され、終了時に閉じられるようです。

リダイレクト

man bash コマンド、またはman bashの日本語版によれば、Linuxのリダイレクト機能では、ファイルディスクリプタを用いて出力する内容を指定することができます。ファイルディスクリプタの番号をnだとすると、

[n]<word
[n]>word

とすることでwordをファイルディスクリプタnとして扱うことができるようになります。nが指定されなかった場合は出力のリダイレクト > では標準出力(fd 1)で、入力のリダイレクト < では標準入力(fd 0)で実行されるようです。

さらに、

[n]<&word
[n]>&word

とすることで、ファイルディスクリプタの複製を行うことができます。wordが数字の場合は、これをファイルディスクリプタとして扱い、wordをコピーしたものをnというファイルディスクリプタに対応づけます。wordが数字ではない場合は出力のリダイレクトとして扱われることになります。

2>&1

上記のように指定すれば、標準エラー出力を標準出力に複製することができます。

以上より、標準エラー出力を捨てる方法と、標準出力と標準エラー出力の両方を捨てる方法を考えます。

標準エラー出力を捨てる方法

command 2> /dev/null

これで標準エラー出力だけを捨てることができます。

標準出力と標準エラー出力の両方を捨てる方法

command > /dev/null 2>&1

少し複雑ですが、commandの標準出力を /dev/null に向け、さらに標準エラー出力を標準入力にコピーすることで、結果的に標準エラー出力も標準出力として /dev/null へ捨てられることになります。

また、man bash コマンドによれば、以下のコマンドはこれと同様の動作をするようです。

command &> /dev/null

>& とする方法もあるようですが、&> を推奨するという記述がありました。ただし、bashのみでの動作ですので注意が必要です。

(参考)上手くいかない例

command 2>&1 > /dev/null

どうやらこの順番では上手くいかないようです。詳しくは標準エラーのリダイレクトにありましたのでそちらを見てもらえたらいいと思います。難しい内容です。

参考文献・サイト

  1. IBM, “/dev/null ファイルで出力を廃棄する”
  2. man bash
  3. 標準エラーのリダイレクト