21

I would like to do the following at one point in a script:

start_time=date

and this after a process or processes have run:

end_time=date

and then do this:

elapsed=$end_time-$start_time
echo "Total of $elapsed seconds elapsed for process"

How would I do this?

2
29

Use the time since epoch to easily identify a span of time in a script

man date
%s     seconds since 1970-01-01 00:00:00 UTC
%N     nanoseconds (000000000..999999999)

.

start_time="$(date -u +%s)"
sleep 5
end_time="$(date -u +%s)"

elapsed="$(($end_time-$start_time))"
echo "Total of $elapsed seconds elapsed for process"

 Total of 5 seconds elapsed for process

Bash doesn't support floating point numbers, so you'll need to use a external tool like bc to compare times like 1475705058.042270582-1475705053.040524971

start_time="$(date -u +%s.%N)"
sleep 5
end_time="$(date -u +%s.%N)"

elapsed="$(bc <<<"$end_time-$start_time")"
echo "Total of $elapsed seconds elapsed for process"

 Total of 5.001884264 seconds elapsed for process
4
  • this is what I was looking for.. can this include microtime? – Oliver Williams Oct 5 '16 at 20:38
  • Try date '+%s.%N' – Miati Oct 5 '16 at 20:58
  • You should call date with date -u to avoid DST and local problems with the command. Please read this answer – Isaac Oct 6 '16 at 2:16
  • Seeing as how (traditionally) bc is implemented with dc, you can use dc directly: elapsed=$(dc -e "$end_time $start_time - p") – Andrew Beals Oct 17 '18 at 18:57
26

bash has a builtin timer variable

start=$SECONDS
# do stuff
end=$SECONDS
duration=$(( end - start ))
echo "stuff took $duration seconds to complete"
1
7

@jasonwryan already suggested it, but I'll throw it in as an answer as it is also my go-to when I want to time a script. To time myscript simply use:

time myscript
2
  • 1
    I will try this from time to time but this is more for when I need to isolate or time sub-sections of my script.. – Oliver Williams Oct 5 '16 at 20:38
  • This is not useful if you want to use the derived elapsed time within the script itself, e.g. to calculate how many units the script was able to process per second. – Hans Ekbrand Jul 13 '20 at 10:25
0

I like @Miata's answer because it draws attention to date +%s solution. However, @Miata includes .%N but I am not sure what benefit you will get looking at nanoseconds when there is the cost of executing the date command in a subshell. So, in practice, date +%s should be sufficient. The other thing to note is date +%s epoch is 1970-01-01 00:00:00 UTC. Which means the time has an absolute epoch and you can share the time measurement between different instances of shell script or different machines.

(( start=$(date +%s) )) # 1604026743
# ... some activity that lasts for, say, 24 seconds
(( end=$(date -u +%s) )) # 1604026767
(( duration=end-start )) # 24

I like @glenn jackman's answer because it refers to SECONDS bash built-in variable. The thing to note here is the epoch is the time when the process was started. So, we can only use this technique to measure times for things that happen within that script:

(( start=SECONDS )) # 10
# ... some activity that lasts for, say, 24 seconds
(( end=SECONDS )) # 34
(( duration=end-start )) # 24

Another thing is I put all my assignments within the (( )) command. i.e. you can rewrite:

cmd=$(( some_expression ))

as

(( cmd=some_expression ))

By doing this, we can minimize the occurrence of the $ symbol.

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.