Write output of `time` in a file, why are parentheses needed?
In ksh
, bash
and zsh
, time
is not a command (builtin or not), it's a reserved word in the language like for
or while
.
It's used to time a pipeline1.
In:
time for i in 1 2; do cmd1 "$i"; done | cmd2 > redir
You have special syntax that tells the shell to run that pipe line:
for i in 1 2; do cmd1 "$i"; done | cmd2 > redir
And report timing statistics for it.
In:
time cmd > output 2> error
It's the same, you're timing the cmd > output 2> error
command, and the timing statistics still go on the shell's stderr.
You need:
{ time cmd > output 2> error; } 2> timing-output
Or:
exec 3>&2 2> timing-output
time cmd > output 2> error 3>&-
exec 2>&3 3>&-
For the shell's stderr to be redirected to timing-output
before the time construct (again, not command) is used (here to time cmd > output 2> error 3>&-
).
You can also run that time
construct in a subshell that has its stderr redirected:
(time cmd > output 2> error) 2> timing-output
But that subshell is not necessary here, you only need stderr to be redirected at the time that time
construct is invoked.
Most systems also have a time
command. You can invoke that one by disabling the time
keyword. All you need to do is quote that keyword somehow as keywords are only recognised as such when literal.
'time' cmd > output 2> error-and-timing-output
But beware the format may be different and the stderr of both time
and cmd
will be merged into error-and-timing-output
.
Also, the time
command, as opposed to the time
construct cannot time pipelines or compound commands or functions or shell builtins...
If it were a builtin command, it might be able to time function invocations or builtins, but it could not time redirections or pipelines or compound commands.
1 Note that bash
has (what can be considered as) a bug whereby time (cmd) 2> file
(but not time cmd | (cmd2) 2> file
for instance) redirects the timing output to file
There's no command named time wc
, time
and wc
are separated word in shell.
Now, there're often two separate program named time
, the one is shell keyword, another one is external command. In shells which time
is a shell keyword, when you type time wc ...
, the shell used its keyword time
instead of the external time utility.
When the shell uses time
keyword, it does not need to fork() new process, the current time
standard in and standard error are not changed. The redirection part in:
time wc file > wc.out 2>&1
affects wc
only.
When you use compound command (list)
:
(time wc file) > wc.out 2>&1
the shell ran time wc file
inside a subshell, (time wc file)
was considered a single command, and the redirection part affects its standard output and standard error, which now include both time
and wc
.
You can make the same effect, without the cost of forking new process by using another form of grouping command {list;}
:
{time wc file;} > wc.out 2>&1
If you use external time
, then you don't face this problem, because it was run in new process:
/usr/bin/time wc file > wc.out 2>&1
Because time
you're executing is bash builtin. Bash processes it in such special way.
If you will use real time
binary, it will act exactly in the way you expect it:
/usr/bin/time wc file > wc.out 2>&1
Though the output of this time is a bit different:
$ /usr/bin/time wc file > wc.out
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata1900maxresident)k
0inputs+8outputs (0major+82minor)pagefaults 0swaps