Since POSIX defines the time utility to write its result on standard error, the only trick you have to be aware of is that there is a bash
built-in time
that behaves slightly differently.
$ time sleep 1
real 0m1.004s
user 0m0.001s
sys 0m0.002s
$ time sleep 1 2>xyz
real 0m1.005s
user 0m0.001s
sys 0m0.003s
$ (time sleep 1) 2>xyz
$ cat xyz
real 0m1.005s
user 0m0.001s
sys 0m0.002s
$ /usr/bin/time sleep 1 2>xyz
$ cat xyz
1.00 real 0.00 user 0.00 sys
$
Testing shown on MacOS X 10.7. Note the difference in output format between built-in and external versions of the time
command. Note also that in the sub-shell format, the built-in time
is redirected normally, but in the simple case, redirecting the output after the built-in time
does not send the output to the same place that the rest of the standard error goes to.
So, these observations allow you to write your elegant script. Probably the simplest method is to wrap your existing script as a function, and then invoke that function via the built-in time
.
Original script
# This is what was in the Exp script before.
# It echoes its name and its arguments to both stdout and stderr
echo "Exp $*"
echo "Exp $*" 1>&2
Revised script
log=./Exp.log
Exp()
{
# This is what was in the Exp script before.
# It echoes its name and its arguments to both stdout and stderr
echo "Exp $*"
echo "Exp $*" 1>&2
}
(time Exp "$@") 2>> $log
Note the careful use of "$@"
in the invocation of the Exp
function to preserve the separate arguments passed on the command line, and the equally deliberate use of $*
inside the function (which loses the separate arguments, but is only for illustrative purposes).
Possible Issue
The only issue with this is that the error output from the original command also goes to the same log file as timing information. That can be resolved but involves tricky multiple redirections that are more likely to confuse than help. However, for the record, this works nicely:
log=./Exp.log
Exp()
{
# This is what was in the Exp script before.
# It echoes its name and its arguments to both stdout and stderr
echo "Exp $*"
echo "Exp $*" 1>&2
}
exec 3>&2
(time Exp "$@" 2>&3 ) 2>> $log