I needed a timer which will start at the very beginning of the script and stops at the end.
6 Answers
If you want the duration in seconds, at the top use
start=$SECONDS
and at the end
duration=$(( SECONDS - start ))
You could use Linux's built-in time
command. From the man page:
time COMMAND [arguments]
time determines which information to display about the resources used by the COMMAND from the string FORMAT. If no format is specified on the command line, but the TIME environment variable is set, its value is used as the format.
To time the cleanup.sh
script, use:
$ time cleanup.sh
-
2
I realise this is a pretty old question but this is the way I do it for anything when I want/need to know how long something took to run.
Bash has a built-in seconds timer in the form of an internal variable named SECONDS
(see: here for other internal variables)
Put SECONDS=0
before whatever you're checking the run time of. It needs to be after any user input to get a good result so if you're prompting for information, put it after the prompt(s).
Then, put this at the end of what you're checking:
if (( $SECONDS > 3600 )) ; then
let "hours=SECONDS/3600"
let "minutes=(SECONDS%3600)/60"
let "seconds=(SECONDS%3600)%60"
echo "Completed in $hours hour(s), $minutes minute(s) and $seconds second(s)"
elif (( $SECONDS > 60 )) ; then
let "minutes=(SECONDS%3600)/60"
let "seconds=(SECONDS%3600)%60"
echo "Completed in $minutes minute(s) and $seconds second(s)"
else
echo "Completed in $SECONDS seconds"
fi
If you only want to know the time in seconds, you can simplify the above to:
echo "Completed in $SECONDS seconds"
As an example:
read -rp "What's your name? " "name"
SECONDS=0
echo "Hello, $name"
if (( $SECONDS > 3600 )) ; then
let "hours=SECONDS/3600"
let "minutes=(SECONDS%3600)/60"
let "seconds=(SECONDS%3600)%60"
echo "Completed in $hours hour(s), $minutes minute(s) and $seconds second(s)"
elif (( $SECONDS > 60 )) ; then
let "minutes=(SECONDS%3600)/60"
let "seconds=(SECONDS%3600)%60"
echo "Completed in $minutes minute(s) and $seconds second(s)"
else
echo "Completed in $SECONDS seconds"
fi
-
5A shortcut for those who don't want such an elaborate time formatting:
date +%T -d "1/1 + $SECONDS sec"
(limited to less than 24h, but you can adapt to add days too)– xhienneCommented Mar 29, 2017 at 0:40 -
Excellent link to TLDP's Internal Variables. Thank you for that! Commented Dec 9, 2019 at 16:02
#!/bin/bash
start=$(date +%s)
#
# do something
sleep 10
#
#
end=$(date +%s)
seconds=$(echo "$end - $start" | bc)
echo $seconds' sec'
echo 'Formatted:'
awk -v t=$seconds 'BEGIN{t=int(t*1000); printf "%d:%02d:%02d\n", t/3600000, t/60000%60, t/1000%60}'
-
1Hi, welcome on the Unix SE! Code-only answers don't look very well, maybe you could explain what your script is doing.– peterhCommented Jun 14, 2018 at 21:44
-
1Why do you multiply by 1000 here and then divide by 1000*modifier later for all of the displayed values?– nemecCommented Oct 11, 2020 at 2:17
@anask do a clever solution for this answer, just I recommend to use the native $SECONDS
instead to create a new one
awk -v t=$SECONDS 'BEGIN{t=int(t*1000); printf "Elapsed Time (HH:MM:SS): %d:%02d:%02d\n", t/3600000, t/60000%60, t/1000%60}'
The purpose of the printf
and the division is to convert the elapsed seconds to the corresponded unity Hours, Mins, Secs, respective.
I've recently been attempting something similar. I would suggest:
date1=$(date +%s)
#Use this arithmetic to determine elapsed time since defining date1
$(( $(date +%s) - $date1 ))
#While loop using timer
while ! [ $(( $(date +%s) - $date1 )) -gt 10 ]; do
#Terminal timer -n won't append new line, so the echo will replace itself.
##There is also some date formatting to achieve: HH:MM:SS.
echo -ne "$(date -u --date @$(( $(date +%s) - $date1 )) +%H:%M:%S)\r"
done
time
command ( time ./script.sh ), to printout current time usedate
command and so on.time yourprogram.sh
, that @Marius Cotofana explained