Print execution time of a shell command - shell

Is is possible to print the execution time of a shell command with following combination?
root#hostname:~# "command to execute" && echo "execution time"

time is a built-in command in most shells that writes execution time information to the tty.
You could also try something like
start_time=`date +%s`
<command-to-execute>
end_time=`date +%s`
echo execution time was `expr $end_time - $start_time` s.
Or in bash:
start_time=`date +%s`
<command-to-execute> && echo run time is $(expr `date +%s` - $start_time) s

Don't forget that there is a difference between bash's builtin time (which should be called by default when you do time command) and /usr/bin/time (which should require you to call it by its full path).
The builtin time always prints to stderr, but /usr/bin/time will allow you to send time's output to a specific file, so you do not interfere with the executed command's stderr stream. Also, /usr/bin/time's format is configurable on the command line or by the environment variable TIME, whereas bash's builtin time format is only configured by the TIMEFORMAT environment variable.
$ time factor 1234567889234567891 # builtin
1234567889234567891: 142662263 8653780357
real 0m3.194s
user 0m1.596s
sys 0m0.004s
$ /usr/bin/time factor 1234567889234567891
1234567889234567891: 142662263 8653780357
1.54user 0.00system 0:02.69elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+215minor)pagefaults 0swaps
$ /usr/bin/time -o timed factor 1234567889234567891 # log to file `timed`
1234567889234567891: 142662263 8653780357
$ cat timed
1.56user 0.02system 0:02.49elapsed 63%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+217minor)pagefaults 0swaps

root#hostname:~# time [command]
It also distinguishes between real time used and system time used.

For a line-by-line delta measurement, try gnonom.
It is a command line utility, a bit like moreutils's ts, to prepend timestamp information to the standard output of another command. Useful for long-running processes where you'd like a historical record of what's taking so long.
Piping anything to gnomon will prepend a timestamp to each line, indicating how long that line was the last line in the buffer--that is, how long it took the next line to appear. By default, gnomon will display the seconds elapsed between each line, but that is configurable.

Adding to #mob's answer:
Appending %N to date +%s gives us nanosecond accuracy:
start=`date +%s%N`;<command>;end=`date +%s%N`;echo `expr $end - $start`

In zsh you can use
=time ...
In bash or zsh you can use
command time ...
These (by different mechanisms) force an external command to be used.

If I'm starting a long-running process like a copy or hash and I want to know later how long it took, I just do this:
$ date; sha1sum reallybigfile.txt; date
Which will result in the following output:
Tue Jun 2 21:16:03 PDT 2015
5089a8e475cc41b2672982f690e5221469390bc0 reallybigfile.txt
Tue Jun 2 21:33:54 PDT 2015
Granted, as implemented here it isn't very precise and doesn't calculate the elapsed time. But it's dirt simple and sometimes all you need.

If you are using zshell, you can have zshell print the time # the start and end of execution. You can accomplish this by adding the following in your ~/.zshrc:
# print time before & after every command
preexec() { eval THEDATE="`date +"[%D_%H:%M:%S] "`"; echo "<CMD STARTED> $THEDATE" }
precmd() { eval THEDATE="`date +"[%D_%H:%M:%S] "`"; echo "<CMD FINISHD> $THEDATE" }
and open a new terminal window to have the changes take effect in all future terminal sessions.

Just ps -o etime= -p "<your_process_pid>"

Related

How to subtract 60 minutes from current time in unix

I'm currently creating a shell script that will run a python code once an hour that collects, processes, and displays data from a radar for the previous hour.
The python code I am using requires a UTC begin time and end time in format "YYYYMMDDHHmm". So far, I have found using the unix command date -u +"%Y%m%d%H%M" will retrieve my current time in the correct format, but I have not been able to find a way to subtract 60 minutes from this first time and have it output the "start" time/
code I have tried:
date +"%Y%m%d%H%M-60" >> out: 201908201833-60
now= date -u +"%Y%m%d%H%M" >> out:201908201834
echo "$now - 60" >> out: - 60
I'm just starting to self teach/learn shell coding and I am more comfortable with python coding which is why my attempts are set up more like how you would write with python. I'm sure there is a way to store the variable and have it subtract 60 from the end time, but I have not been able to find a good online source for this (both on here and via Google).
You can use -d option in date:
date -u +"%Y%m%d%H%M" -d '-60 minutes'
or else subtract 1 hour instead of 60 minutes:
date -u +"%Y%m%d%H%M" -d '-1 hour'
To be able to capture this value in a variable, use command substitution:
now=$(date -u +"%Y%m%d%H%M" -d '-1 hour')
On OSX (BSD) use this date command as -d is not supported:
now=$(date -u -v-1H +"%Y%m%d%H%M")
Your current attempt has some simple shell script errors.
now= date -u +"%Y%m%d%H%M" >> out:201908201834
This assigns an empty string to the variable now and then runs the date command as previously. If the plan is to capture the output to the variable now, the syntax for that is
now=$(date -u +"%Y%m%d%H%M")
Next up, you try to
echo "$now - 60"
which of course will output the literal string
201908201834 - 60
rather than perform arithmetic evaluation. You can say
echo "$((now - 60))"
to subtract 60 from the value and echo that -- but of course, date arithmetic isn't that simple; subtracting 60 from 201908210012 will not produce 201908202312 like you would hope.
If you have GNU date (that's a big if if you really want to target any Unix) you could simply have done
date -u -d "60 minutes ago" +%F%H%M
but if you are doing this from Python anyway, performing the date extraction and manipulation in Python too will be a lot more efficient as well as more portable.
from datetime import datetime, timedelta
dt = datetime.strptime(when,'%Y%m%d%H%M')
print(dt - timedelta(minutes=60))
The shell command substitution $(command) and arithmetic evaluation $((expression)) syntaxes look vaguely similar, but are really unrelated. Both of them have been introduced after the fundamental shell syntax was already stable, so they had to find a way to introduce new syntax which didn't already have a well-established meaning in the original Bourne shell.

Use PS0 and PS1 to display execution time of each bash command

It seems that by executing code in PS0 and PS1 variables (which are eval'ed before and after a prompt command is run, as I understand) it should be possible to record time of each running command and display it in the prompt. Something like that:
user#machine ~/tmp
$ sleep 1
user#machine ~/tmp 1.01s
$
However, I quickly got stuck with recording time in PS0, since something like this doesn't work:
PS0='$(START=$(date +%s.%N))'
As I understand, START assignment happens in a sub-shell, so it is not visible in the outer shell. How would you approach this?
I was looking for a solution to a different problem and came upon this question, and decided that sounds like a cool feature to have. Using #Scheff's excellent answer as a base in addition to the solutions I developed for my other problem, I came up with a more elegant and full featured solution.
First, I created a few functions that read/write the time to/from memory. Writing to the shared memory folder prevents disk access and does not persist on reboot if the files are not cleaned for some reason
function roundseconds (){
# rounds a number to 3 decimal places
echo m=$1";h=0.5;scale=4;t=1000;if(m<0) h=-0.5;a=m*t+h;scale=3;a/t;" | bc
}
function bash_getstarttime (){
# places the epoch time in ns into shared memory
date +%s.%N >"/dev/shm/${USER}.bashtime.${1}"
}
function bash_getstoptime (){
# reads stored epoch time and subtracts from current
local endtime=$(date +%s.%N)
local starttime=$(cat /dev/shm/${USER}.bashtime.${1})
roundseconds $(echo $(eval echo "$endtime - $starttime") | bc)
}
The input to the bash_ functions is the bash PID
Those functions and the following are added to the ~/.bashrc file
ROOTPID=$BASHPID
bash_getstarttime $ROOTPID
These create the initial time value and store the bash PID as a different variable that can be passed to a function. Then you add the functions to PS0 and PS1
PS0='$(bash_getstarttime $ROOTPID) etc..'
PS1='\[\033[36m\] Execution time $(bash_getstoptime $ROOTPID)s\n'
PS1="$PS1"'and your normal PS1 here'
Now it will generate the time in PS0 prior to processing terminal input, and generate the time again in PS1 after processing terminal input, then calculate the difference and add to PS1. And finally, this code cleans up the stored time when the terminal exits:
function runonexit (){
rm /dev/shm/${USER}.bashtime.${ROOTPID}
}
trap runonexit EXIT
Putting it all together, plus some additional code being tested, and it looks like this:
The important parts are the execution time in ms, and the user.bashtime files for all active terminal PIDs stored in shared memory. The PID is also shown right after the terminal input, as I added display of it to PS0, and you can see the bashtime files added and removed.
PS0='$(bash_getstarttime $ROOTPID) $ROOTPID experiments \[\033[00m\]\n'
As #tc said, using arithmetic expansion allows you to assign variables during the expansion of PS0 and PS1. Newer bash versions also allow PS* style expansion so you don't even need a subshell to get the current time. With bash 4.4:
# PS0 extracts a substring of length 0 from PS1; as a side-effect it causes
# the current time as epoch seconds to PS0time (no visible output in this case)
PS0='\[${PS1:$((PS0time=\D{%s}, PS1calc=1, 0)):0}\]'
# PS1 uses the same trick to calculate the time elapsed since PS0 was output.
# It also expands the previous command's exit status ($?), the current time
# and directory ($PWD rather than \w, which shortens your home directory path
# prefix to "~") on the next line, and finally the actual prompt: 'user#host> '
PS1='\nSeconds: $((PS1calc ? \D{%s}-$PS0time : 0)) Status: $?\n\D{%T} ${PWD:PS1calc=0}\n\u#\h> '
(The %N date directive does not seem to be implemented as part of \D{...} expansion with bash 4.4. This is a pity since we only have a resolution in single second units.)
Since PS0 is only evaluated and printed if there is a command to execute, the PS1calc flag is set to 1 to do the time difference (following the command) in PS1 expansion or not (PS1calc being 0 means PS0 was not previously expanded and so didn't re-evaluate PS1time). PS1 then resets PS1calc to 0. In this way an empty line (just hitting return) doesn't accumulate seconds between return key presses.
One nice thing about this method is that there is no output when you have set -x active. No subshells or temporary files in sight: everything is done within the bash process itself.
I took this as puzzle and want to show the result of my puzzling:
First I fiddled with time measurement. The date +%s.%N (which I didn't realize before) was where I started from. Unfortunately, it seems that bashs arithmetic evaluation seems not to support floating points. Thus, I chosed something else:
$ START=$(date +%s.%N)
$ awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$START') }' /dev/null
8.059526s
$
This is sufficient to compute the time difference.
Next, I confirmed what you already described: sub-shell invocation prevents usage of shell variables. Thus, I thought about where else I could store the start time which is global for sub-shells but local enough to be used in multiple interactive shells concurrently. My solution are temp. files (in /tmp). To provide a unique name I came up with this pattern: /tmp/$USER.START.$BASHPID.
$ date +%s.%N >/tmp/$USER.START.$BASHPID ; \
> awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$(cat /tmp/$USER.START.$BASHPID)') }' /dev/null
cat: /tmp/ds32737.START.11756: No such file or directory
awk: cmd. line:1: BEGIN { printf("%fs", 1491297723.111219300 - ) }
awk: cmd. line:1: ^ syntax error
$
Damn! Again I'm trapped in the sub-shell issue. To come around this, I defined another variable:
$ INTERACTIVE_BASHPID=$BASHPID
$ date +%s.%N >/tmp/$USER.START.$INTERACTIVE_BASHPID ; \
> awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)') }' /dev/null
0.075319s
$
Next step: fiddle this together with PS0 and PS1. In a similar puzzle (SO: How to change bash prompt color based on exit code of last command?), I already mastered the "quoting hell". Thus, I should be able to do it again:
$ PS0='$(date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}")'
$ PS1='$(awk "BEGIN { printf(\"%fs\", "$(date +%s.%N)" - "$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)") }" /dev/null)'"$PS1"
0.118550s
$
Ahh. It starts to work. Thus, there is only one issue - to find the right start-up script for the initialization of INTERACTIVE_BASHPID. I found ~/.bashrc which seems to be the right one for this, and which I already used in the past for some other personal customizations.
So, putting it all together - these are the lines I added to my ~/.bashrc:
# command duration puzzle
INTERACTIVE_BASHPID=$BASHPID
date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}"
PS0='$(date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}")'
PS1='$(awk "BEGIN { printf(\"%fs\", "$(date +%s.%N)" - "$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)") }" /dev/null)'"$PS1"
The 3rd line (the date command) has been added to solve another issue. Comment it out and start a new interactive bash to find out why.
A snapshot of my cygwin xterm with bash where I added the above lines to ./~bashrc:
Notes:
I consider this rather as solution to a puzzle than a "serious productive" solution. I'm sure that this kind of time measurement consumes itself a lot of time. The time command might provide a better solution: SE: How to get execution time of a script effectively?. However, this was a nice lecture for practicing the bash...
Don't forget that this code pollutes your /tmp directory with a growing number of small files. Either clean-up the /tmp from time to time or add the appropriate commands for clean-up (e.g. to ~/.bash_logout).
Arithmetic expansion runs in the current process and can assign to variables. It also produces output, which you can consume with something like \e[$((...,0))m (to output \e[0m) or ${t:0:$((...,0))} (to output nothing, which is presumably better). 64-bit integer support in Bash supports will count POSIX nanoseconds until the year 2262.
$ PS0='${t:0:$((t=$(date +%s%N),0))}'
$ PS1='$((( t )) && printf %d.%09ds $((t=$(date +%s%N)-t,t/1000000000)) $((t%1000000000)))${t:0:$((t=0))}\n$ '
0.053282161s
$ sleep 1
1.064178281s
$
$
PS0 is not evaluated for empty commands, which leaves a blank line (I'm not sure if you can conditionally print the \n without breaking things). You can work around that by switching to PROMPT_COMMAND instead (which also saves a fork):
$ PS0='${t:0:$((t=$(date +%s%N),0))}'
$ PROMPT_COMMAND='(( t )) && printf %d.%09ds\\n $((t=$(date +%s%N)-t,t/1000000000)) $((t%1000000000)); t=0'
0.041584565s
$ sleep 1
1.077152833s
$
$
That said, if you do not require sub-second precision, I would suggest using $SECONDS instead (which is also more likely to return a sensible answer if something sets the time).
As correctly stated in the question, PS0 runs inside a sub-shell which makes it unusable for this purpose of setting the start time.
Instead, one can use the history command with epoch seconds %s and the built-in variable $EPOCHSECONDS to calculate when the command finished by leveraging only $PROMPT_COMMAND.
# Save start time before executing command (does not work due to PS0 sub-shell)
# preexec() {
# STARTTIME=$EPOCHSECONDS
# }
# PS0=preexec
# Save end time, without duplicating commands when pressing Enter on an empty line
precmd() {
local st=$(HISTTIMEFORMAT='%s ' history 1 | awk '{print $2}');
if [[ -z "$STARTTIME" || (-n "$STARTTIME" && "$STARTTIME" -ne "$st") ]]; then
ENDTIME=$EPOCHSECONDS
STARTTIME=$st
else
ENDTIME=0
fi
}
__timeit() {
precmd;
if ((ENDTIME - STARTTIME >= 0)); then
printf 'Command took %d seconds.\n' "$((ENDTIME - STARTTIME))";
fi
# Do not forget your:
# - OSC 0 (set title)
# - OSC 777 (notification in gnome-terminal, urxvt; note, this one has preexec and precmd as OSC 777 features)
# - OSC 99 (notification in kitty)
# - OSC 7 (set url) - out of scope for this question
}
export PROMPT_COMMAND=__timeit
Note: If you have ignoredups in your $HISTCONTROL, then this will not report back for a command that is re-run.
Following #SherylHohman use of variables in PS0 I've come with this complete script. I've seen you don't need a PS0Time flag as PS0Calc doesn't exists on empty prompts so _elapsed funct just exit.
#!/bin/bash
# string preceding ms, use color code or ascii
_ELAPTXT=$'\E[1;33m \uf135 '
# extract time
_printtime () {
local _var=${EPOCHREALTIME/,/};
echo ${_var%???}
}
# get diff time, print it and end color codings if any
_elapsed () {
[[ -v "${1}" ]] || ( local _VAR=$(_printtime);
local _ELAPSED=$(( ${_VAR} - ${1} ));
echo "${_ELAPTXT}$(_formatms ${_ELAPSED})"$'\n\e[0m' )
}
# format _elapsed with simple string substitution
_formatms () {
local _n=$((${1})) && case ${_n} in
? | ?? | ???)
echo $_n"ms"
;;
????)
echo ${_n:0:1}${_n:0,-3}"ms"
;;
?????)
echo ${_n:0:2}","${_n:0,-3}"s"
;;
??????)
printf $((${_n:0:3}/60))m+$((${_n:0:3}%60)),${_n:0,-3}"s"
;;
???????)
printf $((${_n:0:4}/60))m$((${_n:0:4}%60))s${_n:0,-3}"ms"
;;
*)
printf "too much!"
;;
esac
}
# prompts
PS0='${PS1:(PS0time=$(_printtime)):0}'
PS1='$(_elapsed $PS0time)${PS0:(PS0time=0):0}\u#\h:\w\$ '
img of result
Save it as _prompt and source it to try:
source _prompt
Change text, ascii codes and colors in _ELAPTXT
_ELAPTXT='\e[33m Elapsed time: '

Mac OS X Shell Script Measure Time Elapsed

How can I measure the time elapsed in milliseconds in a shell script in Mac OS X?
Use the time command (manpage). This will be much cheaper than invoking ruby just to tell you elapsed time:
$ time a_command
To "extract" the real time from the command do (untested):
real_time=$(time a_command | grep ^real | awk 'print $2')
(where a_command can be a shell function if necessary)
This will return the value in minutes and seconds, so if you want the result in milliseconds then use python (or your favourite scripting language) to run the process with timing functions around the outside of the sub-process invocation and you will not incur the cost invoking the scripting language just to get the current time. See this answer and this answer for details.
You may use:
start_ms=$(ruby -e 'puts (Time.now.to_f * 1000).to_i')
# do some work
end_ms=$(ruby -e 'puts (Time.now.to_f * 1000).to_i')
elapsed_ms=$((end_ms - start_ms))
echo "$elapsed_ms ms passed"
OR only shell builtins (works in bash and zsh):
start_ns=$(date +%s%N)
# do some work
end_ns=$(date +%s%N)
elapsed_ms=$(((end_ns - start_ns) / 1000000))

/usr/bin/time --format output elapsed time in milliseconds

I use the /usr/bin/time program to measure the time for a command.
with the --format parameter i can format the output.
e.g.
/usr/bin/time -f "%e" ls
is there a way to output a bigger accuracy of the elapsed seconds? or just output milliseconds, not seconds?
In the manual of /usr/bin/time it only says something about seconds, but maybe there is a way and someone can help me...
thanks!
EDIT:
I know about the bash command "time" which uses the format of the environment variable "TIMEFORMAT". sorry, but i don't wanna change that env-var... seems to risky to me, solution should be something that doesn't change the running system at all :)
One possibility is to use the date command:
ts=$(date +%s%N) ; my_command ; tt=$((($(date +%s%N) - $ts)/1000000)) ; echo "Time taken: $tt milliseconds"
%N should return nanoseconds, and 1 millisecond is 1000000 nanosecond, hence by division would return the time taken to execute my_command in milliseconds.
NOTE that the %N is not supported on all systems, but most of them.
For convenience I made devnull's answer into a script (I named it millisecond-time).
#!/bin/bash
ts=$(date +%s%N) ; $# ; tt=$((($(date +%s%N) - $ts)/1000000)) ; echo "Time taken: $tt milliseconds"
I put the script in /usr/local/bin.
Gave it execute rights chmod +x /usr/local/bin/millisecond-time.
Now I can use it like this: millisecond-time my_command
P.s. This would be a comment if I had the rep'.
There are a couple of things getting confused in this thread.
Bash has a built-in time command which supports a TIMEFORMAT environment variable that will let you format the output. For details on this run man bash and search for TIMEFORMAT.
There is also a standard /usr/bin/time command-line utility which supports a TIME environment variable that will let you format the output (or you can use -f or --format on the command line). For details on this run man time and search for TIME.
If you want the number of seconds the command took to run you can either use the built-in bash command (which supports a maximum precision of three decimal places):
bash# export TIMEFORMAT="%3lR"
bash# time find /etc > /dev/null
0m0.015s
Or you can use the command-line utility (which supports a maximum precision of two decimal places):
shell# export TIME="%E"
shell# /usr/bin/time find /opt/ > /dev/null
0:00.72
As mentioned above neither of these variables are used by anything else and are safe to change.

Custom format for time command

I'd like to use the time command in a bash script to calculate the elapsed time of the script and write that to a log file. I only need the real time, not the user and sys. Also need it in a decent format. e.g 00:00:00:00 (not like the standard output). I appreciate any advice.
The expected format supposed to be 00:00:00.0000 (milliseconds) [hours]:[minutes]:[seconds].[milliseconds]
I've already 3 scripts. I saw an example like this:
{ time { # section code goes here } } 2> timing.log
But I only need the real time, not the user and sys. Also need it in a decent format. e.g 00:00:00:00 (not like the standard output).
In other words, I'd like to know how to turn the time output into something easier to process.
You could use the date command to get the current time before and after performing the work to be timed and calculate the difference like this:
#!/bin/bash
# Get time as a UNIX timestamp (seconds elapsed since Jan 1, 1970 0:00 UTC)
T="$(date +%s)"
# Do some work here
sleep 2
T="$(($(date +%s)-T))"
echo "Time in seconds: ${T}"
printf "Pretty format: %02d:%02d:%02d:%02d\n" "$((T/86400))" "$((T/3600%24))" "$((T/60%60))" "$((T%60))""
Notes:
$((...)) can be used for basic arithmetic in bash – caution: do not put spaces before a minus - as this might be interpreted as a command-line option.
See also: http://tldp.org/LDP/abs/html/arithexp.html
EDIT:
Additionally, you may want to take a look at sed to search and extract substrings from the output generated by time.
EDIT:
Example for timing with milliseconds (actually nanoseconds but truncated to milliseconds here). Your version of date has to support the %N format and bash should support large numbers.
# UNIX timestamp concatenated with nanoseconds
T="$(date +%s%N)"
# Do some work here
sleep 2
# Time interval in nanoseconds
T="$(($(date +%s%N)-T))"
# Seconds
S="$((T/1000000000))"
# Milliseconds
M="$((T/1000000))"
echo "Time in nanoseconds: ${T}"
printf "Pretty format: %02d:%02d:%02d:%02d.%03d\n" "$((S/86400))" "$((S/3600%24))" "$((S/60%60))" "$((S%60))" "${M}"
DISCLAIMER:
My original version said
M="$((T%1000000000/1000000))"
but this was edited out because it apparently did not work for some people whereas the new version reportedly did. I did not approve of this because I think that you have to use the remainder only but was outvoted.
Choose whatever fits you.
To use the Bash builtin time rather than /bin/time you can set this variable:
TIMEFORMAT='%3R'
which will output the real time that looks like this:
5.009
or
65.233
The number specifies the precision and can range from 0 to 3 (the default).
You can use:
TIMEFORMAT='%3lR'
to get output that looks like:
3m10.022s
The l (ell) gives a long format.
From the man page for time:
There may be a shell built-in called time, avoid this by specifying /usr/bin/time
You can provide a format string and one of the format options is elapsed time - e.g. %E
/usr/bin/time -f'%E' $CMD
Example:
$ /usr/bin/time -f'%E' ls /tmp/mako/
res.py res.pyc
0:00.01
Use the bash built-in variable SECONDS. Each time you reference the variable it will return the elapsed time since the script invocation.
Example:
echo "Start $SECONDS"
sleep 10
echo "Middle $SECONDS"
sleep 10
echo "End $SECONDS"
Output:
Start 0
Middle 10
End 20
Not quite sure what you are asking, have you tried:
time yourscript | tail -n1 >log
Edit: ok, so you know how to get the times out and you just want to change the format. It would help if you described what format you want, but here are some things to try:
time -p script
This changes the output to one time per line in seconds with decimals. You only want the real time, not the other two so to get the number of seconds use:
time -p script | tail -n 3 | head -n 1
The accepted answer gives me this output
# bash date.sh
Time in seconds: 51
date.sh: line 12: unexpected EOF while looking for matching `"'
date.sh: line 21: syntax error: unexpected end of file
This is how I solved the issue
#!/bin/bash
date1=$(date --date 'now' +%s) #date since epoch in seconds at the start of script
somecommand
date2=$(date --date 'now' +%s) #date since epoch in seconds at the end of script
difference=$(echo "$((date2-$date1))") # difference between two values
date3=$(echo "scale=2 ; $difference/3600" | bc) # difference/3600 = seconds in hours
echo SCRIPT TOOK $date3 HRS TO COMPLETE # 3rd variable for a pretty output.

Resources