13

I just want to capture the output of a time command i.e:

X=$(time ls)

or

$(time ls) | grep real

The time function spits it to the console though. How do I do this?

12

X=`(time ls) 2>&1 | grep real`

  • You don't need a subshell just for time; Dennis Williamson's answer is better in that regard. – musiphil Nov 1 '13 at 21:32
11

See BashFAQ/032.

$ # captures output of command and time
$ time=$( TIMEFORMAT="%R"; { time ls; } 2>&1 )    # note the curly braces

$ # captures the time only, passes stdout through
$ exec 3>&1 4>&2
$ time=$(TIMEFORMAT="%R"; { time ls 1>&3 2>&4; } 2>&1)
bar baz
$ exec 3>&- 4>&-

The time will look like "0.000" using TIMEFORMAT="%R" which will be the "real" time.

  • could you explain a little how this works ? I've uses a snippet like this cargo cult style for years. Whats stream 3 and 4 ? and the '-' ? – Sirex Sep 15 '16 at 2:46
  • 1
    @Sirex: Streams 3 and 4 are streams created by the exec command in my answer using available file descriptors. Any available file descriptors could be used. Streams 3 and 4 are copies of 1 (stdout) and 2 (stderr), respectively. This allows the output of ls to pass normally to stdout and stderr via 3 and 4 while the output of time (which normally goes to stderr) is redirected to the original stdout (1) and then captured in the variable using command substitution. As you can see in my example, the filenames bar and baz are output to the terminal. ... – Dennis Williamson Sep 15 '16 at 15:48
  • 1
    ... Once finished, the extra streams are closed using the trailing -. – Dennis Williamson Sep 15 '16 at 15:49
4

Time writes its output to STDERR rather than STDOUT. Making matters worse, by default 'time' is a shell builtin command, so if you attempt 'time ls 2>&1' the '2>&1' only applies to 'ls'.

The solution would probably be something like:

/usr/bin/time -f 'real %e' -o OUTPUT_FILE ls > /dev/null 2>&1<br>
REALTIME=$(cat OUTPUT_FILE | cut -f 2 -d ' ')

There are more fancy ways to do it, but that is the clear/simple way.

  • I am interested in doing this without -o. Can you post one of the fancy methods you were thinking of :) ? – David Doria Apr 22 '14 at 17:12
0

@Dennis Williamson's answer is great, but it doesn't help you store the command's output in one variable, and the output of time in another variable. This is actually not possible using file descriptors.

If you want to record how long a program takes to run, you could do this by just subtracting the start time from the end time. Here is a simple example that shows how many milliseconds a program took to run:

START_TIME=$(date +%s%3N)
OUTPUT=$(ls -l)
ELAPSED_TIME=$(expr $(date +%s%3N) - $START_TIME)
echo "Command finished in $ELAPSED_TIME milliseconds"

This is not quite as accurate as the time command, but it should work perfectly fine for most bash scripts.

Unfortunately Mac's date command doesn't support the %N format, but you can install coreutils (brew install coreutils) and use gdate:

START_TIME=$(gdate +%s%3N)
OUTPUT=$(ls -l)
ELAPSED_TIME=$(expr $(gdate +%s%3N) - $START_TIME)
echo "Command finished in $ELAPSED_TIME milliseconds"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.