13

I am trying to time something using:

/usr/bin/time myCommand

However, since /usr/bin/time writes to stderr, if myCommand also writes to stderr, I will get more than just time's output on the stream. What I want to do is, redirect all of myCommand's output to /dev/null, but still write time's output to stderr. Using an example myCommand that writes to stderr of ls /nofile, we see that (obviously) there is no output at all with the following:

$ /usr/bin/time ls /nofile 2> /dev/null
$

Without any redirection, we see both the output from ls (to stderr) and the output from time (also to stderr):

$ /usr/bin/time ls /nofile
ls: cannot access /nofile: No such file or directory
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

What I want is something that simply produces:

$ /usr/bin/time ls /nofile > RedirectThatImAskingFor
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

Any ideas?

2 Answers2

24

In ksh, bash and zsh, time is a keyword, not a builtin. Redirections on the same line apply only to the command being timed, not to the output of time itself.

$ time ls -d / /nofile >/dev/null 2>/dev/null

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

To redirect the output from time itself in these shells, you need to use an additional level of grouping.

{ time mycommand 2>&3; } 3>&2 2>mycommand.time

If you use the GNU version of the standalone time utility, it has a -o option to write the output of time elsewhere than stderr. You can make time write to the terminal:

/usr/bin/time -o /dev/tty mycommand >/dev/null 2>/dev/null

If you want to keep the output from time on its standard error, you need an extra level of file descriptor shuffling.

/usr/bin/time -o /dev/fd/3 mycommand 3>&2 >/dev/null 2>/dev/null

With any time utility, you can invoke an intermediate shell to perform the desired redirections. Invoking an intermediate shell to perform extra actions such as cd, redirections, etc. is pretty common — it's the kind of little things that shells are designed to do.

/usr/bin/time sh -c 'exec mycommand >/dev/null 2>/dev/null'
  • A couple of follow ups: 1) What does the 'exec' in your last suggestion do? It seems to work without it: /usr/bin/time sh -c 'exec ls /nofile &>./output.dat' 2) Is an "intermediate shell" the same as a "subshell" (which you would get I think using parentheses?). I had been trying things like /usr/bin/time (ls /nofile &>./output.dat) to no avail. 3) What is /dev/tty ? I know tty0 is stdin, tty1=stdout, tty2=stderr, but what about just 'tty'? – David Doria Apr 23 '14 at 12:07
  • With the /dev/fd3 option, it seems you are saying to write the -o output to 3, then redirect 3 to 2, 1 to null, and 2 to null. Shouldn't that send 3 to null also since the redirections happen left to right?
  • – David Doria Apr 23 '14 at 12:08
  • 1
    @DavidDoria exec replaces the shell by the specified program instead of running that program as a subprocess. Some shells perform this optimization automatically when a command is the last one in a script. “Intermediate shell” means just that: a shell that's between time and mycommand; it is unrelated to subshells. /dev/tty is the terminal that the command is running on (it is unrelated to /dev/ttyNUM which are physical consoles; you're confusing with file descriptors: stdin is /dev/fd/0, etc). – Gilles 'SO- stop being evil' Apr 23 '14 at 17:16
  • @DavidDoria Changing what a file descriptor is connected to happens from left to right, which has the opposite effect. See http://unix.stackexchange.com/questions/23964/why-is-redirecting-stderr-to-dev-null-done-this-way or http://unix.stackexchange.com/questions/37660/order-of-redirections – Gilles 'SO- stop being evil' Apr 23 '14 at 17:20