In its simplest form, this sounds like what you're after.
now(){
date -u +%s.%N
}
measure_time(){
local elapsed="$(bc <<<"$end_time-$start_time")"
echo "Total of $elapsed seconds elapsed for process"
}
start_time="$(now)"
sleep 5
end_time="$(now)"
measure_time
You could make the now function accept a named variable and adapt the measure_time function to handle that, but it would be an unnecessary complication if your use case is to track one process at a time.
Having said that, here's an iteration in that direction. start and end are arbitrary labels, so you could call them what ever suits, if you were tracking multiple events.
stamp(){
time[$1]="$(date -u +%s.%N)"
}
measure_time(){
local elapsed="$(bc <<<"${time[$2]}-${time[$1]}")"
echo "Total of $elapsed seconds elapsed for process"
}
declare -A time=()
stamp start
sleep 5
stamp end
measure_time start end
EDIT:
Caveat
As the figures in roaima's answer show, this is not going to be high precision, because each action (particularly so sub shells and external processes) will pad the reported time out by some fraction of a second. This probably doesn't matter for multi-minute processes (in which case why measure nano seconds?) but will become more pronounced at lower run times, to the point of being almost meaningless. Though the problem was rather less severe in my tests as compared to roaima's. It rather depends on what you are using that data for.
ANOTHER EDIT:
Responding to QuartzCrystal's fair comment, herein lies a further iteration which, it turns out, is converging on roaima's answer -- probably indicating they are on the "best" track.
_stamp(){
time[${1:?}]="$(date -u +%s.%N)"
}
start() {
_stamp "start${1:+${1}}"
}
end() {
_stamp "end${1:+${1}}"
}
measure_time(){
local elapsed="$(bc <<<"${time[end${1:+_${1}}]}-${time[start${1:+_${1}}]}")"
echo "Total of $elapsed seconds elapsed${1:+ for process ${1}}"
}
declare -A time=()
_start
sleep 5
_end
measure_time
_start foo
sleep 1
_start bar
sleep 2
_end foo
_end bar
measure_time foo
measure_time bar
hello() { sleep 1; echo hi; }And you use:value=$(hello) ; echo $valueThe output will behi– Edgar Magallon Sep 11 '22 at 07:28SECONDSvariable - see for example Time elapsed of a bash script (days/minutes/seconds) – steeldriver Sep 11 '22 at 12:41timeinside a script (also on a function)? Seetype time,help timeandman time. General usetime MyExecutableScript.shortime /bin/bash MyScript.sh. In your script can be something likeMyFunction(){....}thentime MyFunctionorA="$((time MyFunction) 2>&1)". Note that you need a subshell(...)to redirect the output of time. – Hastur Sep 11 '22 at 15:53date -u +%sjust before the start and just after the end of a command, and the shell can do the integer subtraction to give you the elapsed time. No need to callbcto do floating point operations. But if sub-second precision is what you need, it's what you need. – Sotto Voce Sep 11 '22 at 19:01SECONDSvariable. No external executable to call, less cpu time wasted. – QuartzCristal Sep 12 '22 at 05:50