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?
X=`(time ls) 2>&1 | grep real`
time
; Dennis Williamson's answer is better in that regard.
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.
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. ...
Sep 15, 2016 at 15:48
-
.
Sep 15, 2016 at 15:49
set -x
) adds some unwanted output to the result. I solved it by adding set +x
so that scripts won't fail while debugging. So the solution that worked for me: time=$(set +x; TIMEFORMAT="%R"; { time ls 1>&3 2>&4; } 2>&1)
May 3, 2023 at 14:16
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.
The cleanest approach is to combine a temp file and use GNU's time.
command="sleep 1"
saved_timing=`mktemp`
/usr/bin/time --format="%E real" -o "$saved_timing" $command
elapsed=$(cat "$saved_timing")
echo $elapsed
This will not bypass normal command output and you don't have to care about the file either since it will be deleted on it own.
@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"