timeコマンドの出力先はどこなのか?

timeコマンドの出力先が標準出力だったか標準エラー出力だったかを確認しようと思って,コマンドを叩いてみた.

$ time echo foo 1>/dev/null

real	0m0.000s
user	0m0.000s
sys	0m0.000s
$ time echo foo 2>/dev/null
foo

real	0m0.000s
user	0m0.000s
sys	0m0.000s

標準出力も標準エラー出力も出力先ではない??じゃあ出力されているのはなんなんだ..man timeで確認してみる.

 ...When command finishes, time writes a message to  standard
   error giving timing statistics about this program run.

標準エラー出力に書き込むと書いてある.ではなぜ2>/dev/nullで出力先が/dev/nullに切り替わらないのか?

理由

timeの文法は以下の通り.

time [options] command [arguments...]

time echo foo 2>/dev/nullの場合,

  • options: なし
  • command: echo
  • arguments: foo 2>/dev/null となる.つまり,timeecho foo 2>dev/nullの実行時間を計測して標準エラー出力に書き込んでいた,ということ.

では,echo fooまでをtimeコマンドの引数にするにはどうすればよいかというと,code blockかsubshellを使ってtimeコマンドに対する引数の終わりを明示してやればよいようだ.

$ time { echo foo; } 2>/dev/null  # code blockの場合
foo
$ time ( echo foo ) 2>/dev/null  # subshellの場合
foo

ちなみにcode blockを使うときは,最後のセミコロンを忘れないこと.セミコロンがないと文法エラーになる.