273

Just a little question about timing programs on Linux: the time command allows to measure the execution time of a program:

[ed@lbox200 ~]$ time sleep 1

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

Which works fine. But if I try to redirect the output to a file, it fails.

[ed@lbox200 ~]$ time sleep 1 > time.txt

real    0m1.004s
user    0m0.001s
sys     0m0.004s

[ed@lbox200 ~]$ cat time.txt 
[ed@lbox200 ~]$ 

I know there are other implementations of time with the option -o to write a file but my question is about the command without those options.

Any suggestions ?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
ed82
  • 3,007
  • 3
  • 15
  • 11
  • 3
    Possible duplicate of [bash script write executing time in a file](http://stackoverflow.com/questions/13176611/bash-script-write-executing-time-in-a-file), and I'm far from convinced that this is the first such question. – Jonathan Leffler Nov 13 '12 at 07:33
  • 1
    This is a duplicate of http://stackoverflow.com/questions/2408981/how-can-i-redirect-the-output-of-the-time-command – codeforester Jan 20 '17 at 23:52

12 Answers12

360

Try

{ time sleep 1 ; } 2> time.txt

which combines the STDERR of "time" and your command into time.txt

Or use

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

which puts STDERR from "sleep" into the file "sleep.stderr" and only STDERR from "time" goes into "time.txt"

benrifkah
  • 1,526
  • 14
  • 31
January
  • 16,320
  • 6
  • 52
  • 74
  • 3
    Thanks, that answers precisely my question. If I correctly understood, the time command's result can be obtained from stderr? – ed82 Nov 13 '12 at 17:58
  • 11
    Yes, but you must put it in curly brackets, otherwise the redirection will be part of the command that `time` evaluates. – January Nov 13 '12 at 22:05
  • Not a valid answer, even with the curly brackets update. Using a command which generates error output will show that in the above syntax time.txt will contain the command's error and time's output. It seems the original question is asking how to capture time output independently from _any_ command output. A problem I have not yet solved. – Daniel Jan 08 '14 at 15:51
  • 6
    @Daniel You could always redirect the internal command output separately (i.e. { time sleep 1 2> sleepStdErr.txt ; } 2> time.txt ) and that would get you only the time output. I'm not sure if there's a way to get it independently otherwise. – gms7777 Jan 14 '14 at 16:25
  • @gms7777 Thanks. I can grep/cat the output files as needed so that syntax splits them up for my needs. – Daniel Jan 15 '14 at 19:46
  • 11
    If you want to use time with something like grep that reads off of stdout try `{ time sleep 1; } 2>&1 | grep real`. This sends stderr to stdout which grep can then read. – clayzermk1 Jul 31 '14 at 20:16
  • 13
    do NOT forget the ';' character before closing '}' , it will NOT work without (I did, and ... wonder why isn't working :) ) – THESorcerer Sep 28 '15 at 12:21
  • To store it in a variable use `timer=$({ time sleep 2; } 2>&1)` and print the output using `echo "$timer"` – Soubhik Mazumdar Dec 13 '22 at 13:18
70

Simple. The GNU time utility has an option for that.

But you have to ensure that you are not using your shell's builtin time command, at least the bash builtin does not provide that option! That's why you need to give the full path of the time utility:

/usr/bin/time -o time.txt sleep 1
cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
55

Wrap time and the command you are timing in a set of brackets.

For example, the following times ls and writes the result of ls and the results of the timing into outfile:

$ (time ls) > outfile 2>&1

Or, if you'd like to separate the output of the command from the captured output from time:

$ (time ls) > ls_results 2> time_results
sampson-chen
  • 45,805
  • 12
  • 84
  • 81
  • 15
    It is unnecessary to introduce a subshell here. – January Nov 13 '12 at 07:01
  • 2
    @sampson-chen That only works because ls does not write anything to stderr right? How would you "separate" the output of 'time' from that of the command to be run if the command writes to both stdout and stderr? – David Doria Apr 22 '14 at 17:07
  • @January comment could be more useful. Using parentheses starts a new shell. To group the output without starting a new shell, use curly braces. `{ time ls }` – Eyal Feb 04 '21 at 06:03
18

If you care about the command's error output you can separate them like this while still using the built-in time command.

{ time your_command 2> command.err ; } 2> time.log

or

{ time your_command 2>1 ; } 2> time.log

As you see the command's errors go to a file (since stderr is used for time).

Unfortunately you can't send it to another handle (like 3>&2) since that will not exist anymore outside the {...}

That said, if you can use GNU time, just do what @Tim Ludwinski said.

\time -o time.log command
rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Mark
  • 18,730
  • 7
  • 107
  • 130
10

Since the output of 'time' command is error output, redirect it as standard output would be more intuitive to do further processing.

{ time sleep 1; } 2>&1 |  cat > time.txt
jaycee xu
  • 111
  • 1
  • 3
6

If you are using GNU time instead of the bash built-in, try

time -o outfile command

(Note: GNU time formats a little differently than the bash built-in).

Tim Ludwinski
  • 2,704
  • 30
  • 34
  • 1
    This, thank you. And you can use `\time -o outfile command` (with `\`) for use GNU instead of built in. – Mark Apr 05 '15 at 23:40
5
&>out time command >/dev/null

in your case

&>out time sleep 1 >/dev/null

then

cat out
alinsoar
  • 15,386
  • 4
  • 57
  • 74
  • 4
    Elegant idea, but leads to the shell not using its built-in command. If you don't have a real `time` binary installed, `out` will contain something like `bash: time: command not found`. – scy Mar 05 '14 at 12:00
  • Also the format for the GNU time is not the same as the bash builtin, causing problems for automatic parsing. – Guss Mar 12 '15 at 12:37
5

I ended up using:

/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
  • Where "a" is append
  • Where "o" is proceeded by the file name to append to
  • Where "f" is format with a printf-like syntax
  • Where "%E" produces 0:00:00; hours:minutes:seconds
  • I had to invoke /usr/bin/time because the bash "time" was trampling it and doesn't have the same options
  • I was just trying to get output to file, not the same thing as OP
Locane
  • 2,886
  • 2
  • 24
  • 35
3

If you don't want to touch the original process' stdout and stderr, you can redirect stderr to file descriptor 3 and back:

$ { time { perl -le "print 'foo'; warn 'bar';" 2>&3; }; } 3>&2 2> time.out
foo
bar at -e line 1.
$ cat time.out

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

You could use that for a wrapper (e.g. for cronjobs) to monitor runtimes:

#!/bin/bash

echo "[$(date)]" "$@" >> /my/runtime.log

{ time { "$@" 2>&3; }; } 3>&2 2>> /my/runtime.log
Tobias Gödderz
  • 321
  • 1
  • 2
2
#!/bin/bash

set -e

_onexit() {
    [[ $TMPD ]] && rm -rf "$TMPD"
}

TMPD="$(mktemp -d)"
trap _onexit EXIT

_time_2() {
    "$@" 2>&3
}

_time_1() {
    time _time_2 "$@"
}

_time() {
    declare time_label="$1"
    shift
    exec 3>&2
    _time_1 "$@" 2>"$TMPD/timing.$time_label"
    echo "time[$time_label]"
    cat "$TMPD/timing.$time_label"
}

_time a _do_something
_time b _do_another_thing
_time c _finish_up

This has the benefit of not spawning sub shells, and the final pipeline has it's stderr restored to the real stderr.

Adam Heath
  • 21
  • 1
0

If you are using csh you can use:

/usr/bin/time --output=outfile -p $SHELL  -c 'your command'

For example:

/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
Mihai Chelaru
  • 7,614
  • 14
  • 45
  • 51
0

If you want just the time in a shell variable then this works:

var=`{ time <command> ; } 2>&1 1>/dev/null`
Samuel
  • 8,063
  • 8
  • 45
  • 41