I wish to find out how long an operation takes in a Linux shell script. How can I do this?
6 Answers
Using the time command, as others have suggested, is a good idea.
Another option is to use the magic built-in variable $SECONDS, which contains the number of seconds since the script started executing. You can say:
START_TIME=$SECONDS
dosomething
ELAPSED_TIME=$(($SECONDS - $START_TIME))
I think this is bash-specific, but since you're on Linux, I assume you're using bash.

- 46,189
- 17
- 92
- 133
-
5The only caveat I'd add here is that using all-caps names for your own variables is bad form, since it means you can overwrite shell-builtin variables by mistake (f/e, if someone assigns to `SECONDS`, it stops having its special meaning). See POSIX spec @ http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html, reserving lowercase for application use, keeping in mind that shell and environment variables share a single namespace -- *The name space of environment variable names containing lowercase letters is reserved for applications.* – Charles Duffy Mar 14 '19 at 20:18
Use the time
command. time ls /bin
.

- 42,110
- 11
- 57
- 76
-
1`time` is **not suitable** when you are executing **complex command sequence** – Shiplu Mokaddim Dec 26 '13 at 07:06
-
4
-
-
3@shiplu.mokadd.im - why not suitable? Explain. Seems fine/accurate to me and been using for years... – B. Shea May 23 '16 at 16:29
-
1@Keith This has some issues, like `/usr/bin/time -f '%C => %E' (ls / ; sleep 2; ls /bin)` throws `bash: syntax error near unexpected token '('` – Shiplu Mokaddim Jul 01 '19 at 10:53
-
Cannot get it to work with a pipe (grep filter) in the time'd command. – JeffRSon Mar 18 '22 at 14:36
Try following example:
START_TIME=$SECONDS
# do something
sleep 65
ELAPSED_TIME=$(($SECONDS - $START_TIME))
echo "$(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
#> 1 min 5 sec

- 419
- 4
- 6
Many of the answers mention $SECONDS
, but that variable is actually even better than they realize:
Assignment to this variable resets the count to the value assigned, and the expanded value becomes the value assigned plus the number of seconds since the assignment.
This means you can simply query this variable directly at the end of your script to print the elapsed time:
#!/usr/bin/env bash
# Do stuff...
echo "Script finished in $SECONDS seconds."
You can also time smaller sections like so:
#!/usr/bin/env bash
# Do stuff
SECONDS=0
# Do timed stuff...
echo "Timed stuff finished in $SECONDS seconds."

- 393
- 4
- 7
Here is the script to find the time elapsed in milliseconds. Replace the sleep 60 line with the code you want to execute.
a=0
while [ $a -lt 10 ]
do
START_TIME=`echo $(($(date +%s%N)/1000000))`
sleep 3
END_TIME=`echo $(($(date +%s%N)/1000000))`
ELAPSED_TIME=$(($END_TIME - $START_TIME))
echo $ELAPSED_TIME
if [ $a -eq 10 ]
then
break
fi
a=`expr $a + 1`
done

- 39,467
- 16
- 112
- 140

- 75
- 2
- 6
GNU time
I'm also a big fun of the GNU time
command: https://www.gnu.org/software/time/ which offers some important options compared to the time
Bash built-in.
Sample usage:
env time --format '%e' --output time.log sleep 1
Output:
1.00
Explanation:
env
: to find/usr/bin/time
instead of the Bash built-in--format '%e'
: print time in seconds, seeman time
.This is often what I want when benchmarking: a single number rather than minutes + seconds.
And an important pattern I often use is:
bench-cmd() (
logfile=time.log
echo "cmd $@" >> "$logfile"
printf 'time ' >> "$logfile"
bench_cmd="env time --append --format '%e' --output '$logfile' $@"
eval "$bench_cmd"
echo >> "$logfile"
)
rm -f time.log
bench-cmd sleep 1
bench-cmd sleep 2
bench-cmd sleep 3
cat time.log
Output:
cmd sleep 1
time 1.00
cmd sleep 2
time 2.00
cmd sleep 3
time 3.00
Explanation:
--output
: output the time to a file.By default, the output goes to stderr, so this option is important to separate the timing from the stderr of the command.
--append
: append to the file instead of overwriting.This allows me to concentrate the entire benchmark output in a single file.

- 347,512
- 102
- 1,199
- 985