How to measure time of program execution and store that inside a variable
In order to find out how long certain operations within a Bash (v4+) script take, I would like to parse the output from the
timecommand "separately" and (ultimately) capture it within a Bash variable (
Now, I am using
time -f '%e' ...(or rather
command time -f '%e' ...because of the Bash built-in), but since I already redirect the output of the executed command I'm really lost as to how I would go about to capture the output of the
timecommand. Basically the problem here is to separate the output of
timefrom the output of the executed command(s).
What I want is the functionality of counting the amount of time in seconds (integers) between starting a command and its completion. It doesn't have to be the
timecommand or the respective built-in.
Edit: given the two useful answers below, I wanted to add two clarifications.
- I do not want to throw away the output of the executed command, but it will not really matter whether it ends up on stdout or stderr.
- I would prefer a direct approach over an indirect one (i.e. catching output directly as opposed to store it in intermediate files).
The solution using
dateso far comes closes to what I want.
The most direct way to get the data and handle it while still letting it run normally would be to do it in a C program using `fork()`, `execvp()` and `wait3()/wait4()`. This is ultimately what time and friends are doing. I'm not aware of a simle way to do it in bash/perl without redirecting to a file or similar approach.
To get the output of
timeinto a var use the following:
[email protected] $ mytime="$(time ( ls ) 2>&1 1>/dev/null )" [email protected] $ echo "$mytime" real 0m0.006s user 0m0.001s sys 0m0.005s
You can also just ask for a single time type, e.g. utime:
[email protected] $ utime="$( TIMEFORMAT='%lU';time ( ls ) 2>&1 1>/dev/null )" [email protected] $ echo "$utime" 0m0.000s
To get the time you can also use
date +%s.%N, so take it before and after execution and calculate the diff:
START=$(date +%s.%N) command END=$(date +%s.%N) DIFF=$(echo "$END - $START" | bc) # echo $DIFF
I didn't want to throw away the output from the command though. So I guess your third code block is closest to what I had in mind. Although I'd write the last one as `DIFF=$((END-START))`, making use of the arithmetic expressions. :) ... thanks for the answer. +1
@STATUS_ACCESS_DENIED: Bash doesn't do floating point arithmetic, so if you want better than second resolution (`.%N` in binfalse's code), you either need `bc` or fancier calculations.
@Gilles: I know. As I wrote in my question integers are fine. No need to have a higher resolution than second. But thanks, the date invocation would have to be changed. I had realized that, though.
FYI, the date formatting %N doesn't seem to work on Mac OS X, it just returns "N". Ok on Ubuntu.
Note that while the `time (cmd) 2> something` works at redirecting the timing output to `file`, it's not meant to (as per documentation), doesn't in other shells where `time` is a keyword and could be considered as a bug. I wouldn't rely on it as it may not work in future versions of `bash`.