118

I tried to redirect the output of the time command, but I couldn't:

$time ls > filename
real    0m0.000s
user    0m0.000s
sys     0m0.000s

In the file I can see the output of the ls command, not that of time. Please explain, why I couldn't and how to do this.

Jens
  • 69,818
  • 15
  • 125
  • 179
abubacker
  • 4,638
  • 6
  • 32
  • 35

8 Answers8

151

no need to launch sub shell. Use a code block will do as well.

{ time ls; } 2> out.txt

or

{ time ls > /dev/null 2>&1 ; } 2> out.txt
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • 1
    Agreed, Best answer. Gives you the option to ditch the ls results and just get the time. Thank you ghostdog74 – rd42 Sep 10 '11 at 11:43
  • 1
    This worked with AIX when nothing could redirect the output of the "hostent" command. Thank you! – Hugo May 01 '15 at 04:04
  • 1
    Clarification on the `2>` please. Where can I learn about these? – hello_there_andy Feb 20 '17 at 23:47
  • 4
    how do I do it if I want both > and 2> at the same time? –  May 16 '17 at 15:29
  • how does this work? why is a subshell or block needed here? – fuzzyTew Apr 01 '23 at 20:55
  • Looks like you can capture both stdout and stderr with such as `{ time ls; } >out.txt 2>&1` . I'm guessing that time is a builtin that writes to stderr regardless of redirections placed on the same line. – fuzzyTew Apr 01 '23 at 20:57
115

you can redirect the time output using,

(time ls) &> file

Because you need to take (time ls) as a single command so you can use braces.

Motti
  • 110,860
  • 49
  • 189
  • 262
sganesh
  • 1,731
  • 1
  • 13
  • 14
  • 1
    yeah relly fine , but the question is how they did this ? – abubacker Mar 09 '10 at 12:41
  • 2
    time command will take the arguments as a command. But parenthesis will group that as a one command. Ex: time ls > file1.txt In arguments, 0 = time 1 = "ls > file1.txt" – sganesh Mar 09 '10 at 12:49
  • 11
    And time command prints the output in stderr. So you can use (time ls) 2> file – sganesh Mar 09 '10 at 12:54
  • 7
    Clarification on the `&>` please, where can I learn about these? – hello_there_andy Feb 20 '17 at 23:47
  • 5
    @hello_there_andy `&>file` is analogous to `>file 2>&1`. It directs both stdout and stderr. – ktbiz Aug 17 '17 at 02:21
  • 1
    @hello_there_andy: [This page](https://www.tldp.org/LDP/abs/html/io-redirection.html) has some great information on I/O redirection in BASH. It should help you to understand `&>` as well as other syntax. – jvriesem May 30 '18 at 18:46
35

The command time sends it's output to STDERR (instead of STDOUT). That's because the command executed with time normally (in this case ls) outputs to STDOUT.

If you want to capture the output of time, then type:

(time ls) 2> filename

That captures only the output of time, but the output of ls goes normal to the console. If you want to capture both in one file, type:

(time ls) &> filename

2> redirects STDERR, &> redirects both.

Mnementh
  • 50,487
  • 48
  • 148
  • 202
  • 1
    This answer actually answers *why* the OP's redirect wasn't working, which was one of the questions the OP was asking. Nobody else addresses this. – NeutronStar Jun 01 '16 at 14:27
  • how would one pipe to another process with this? – Paul Jun 15 '20 at 22:42
11

time is shell builtin and I'm not sure if there is way to redirect it. However you can use /usr/bin/time instead, which definitely accept any output redirections.

Michal Čihař
  • 9,799
  • 6
  • 49
  • 87
  • 1
    /usr/bin/time --output filename ls – chub Mar 09 '10 at 12:39
  • 4
    The builtin time works well with output-redirection. It only outputs on STDERR, not on STDOUT. – Mnementh Mar 09 '10 at 13:09
  • The problem is that builtin commands are executed within the shell environment itself, not a subshell. Since the stderr of your shell is typically connected to the terminal, redirection won't do anything. To redirect the builtin time, I believe you'd have to do something like `bash time mycmd 2>file`. Or just call `/usr/bin/time` as was mentioned. – ktbiz Aug 17 '17 at 02:36
  • You can also use the non-built-in without specifying the full path: https://stackoverflow.com/questions/29540540/how-do-i-prevent-bash-to-use-a-builtin-command – Ciro Santilli OurBigBook.com Apr 04 '18 at 22:44
10

The reason why redirection does not seem to work with time is that it's a bash reserved word (not a builtin!) when used in front of a pipeline. bash(1):

If the time reserved word precedes a pipeline, the elapsed as well as user and system time consumed by its execution are reported when the pipeline terminates.

So, to redirect output of time, either use curly braces:

{ time ls; } 2> filename

Or call /usr/bin/time:

/usr/bin/time ls 2> filename
user1338062
  • 11,939
  • 3
  • 73
  • 67
7

If you don't want to mix output from time and the command. With GNU time, you can use -o file like:

/usr/bin/time -o tim grep -e k /tmp 1>out 2>err

while tim is output of time, out and err are stdout and stderr from grep.

Ding-Yi Chen
  • 2,830
  • 33
  • 27
2

I use the redirection of stdout and stderr method with braces for testing.
The &>>rpt represents this >>rpt 2>&1 but shorter.
The braces will execute a command(s) in the current shell.   See: man bash

{ time ls a*; } &>>rpt
1

Not the canonical use case, but another way to go.

Longer running simple tasks can be launched in a detached "screen" terminal with logged output. You could even give the log a unique name.

Primarily this method is good for something that will take hours and is invoked over SSH with a need to "check up on" from time to time. In preference to backgrounding and disowning.

screen -dmL time -v ./crackpassword 

You get the same output a terminal would get, with the caveat that this is asynchronous. Of course it could be a script. The output may need tweaking.

mckenzm
  • 1,545
  • 1
  • 12
  • 19