I have a bash script and at certain points I am using echo to put some messages in a log file. The problem that I have is related to the DATE variable which will be static throughout the entire execution of the script.
I have this basic script below to illustrate the problem:
#!/bin/bash
DATE=`date "%Y-%m-%dT%H:%M:%S%:z"`
echo "script started at $DATE"
echo "doing something"
sleep 2
echo "script finished at $DATE"
If I execute this script, the output of the $DATE variable is the same in both lines. Is there some bash magic that could nicely resolve this without having to replace $DATE with the command itself on each line?
Thanks in advance
CodePudding user response:
With bash version 4.3 , you can use the builtin printf
to format datetimes. -1
below is a magic value that means "now".
#!/bin/bash
datefmt='%Y-%m-%dT%H:%M:%S%z'
printf "script started at %($datefmt)T\n" -1
echo "doing something"
sleep 2
printf "script finished at %($datefmt)T\n" -1
bash didn't recognize %:z
for me.
CodePudding user response:
Newer versions of the bash/printf
builtin have support for generating datetime stamps without the need to spawn a subprocess to call date
:
$ builtin printf --help
...snip...
Options:
-v var assign the output to shell variable VAR rather than
display it on the standard output
...snip...
In addition to the standard format specifications described in printf(1),
printf interprets:
%b expand backslash escape sequences in the corresponding argument
%q quote the argument in a way that can be reused as shell input
%(fmt)T output the date-time string resulting from using FMT as a format
string for strftime(3)
... snip ...
Instead of spawning a subprocess to call date
, eg:
logdt=`date "%Y-%m-%dT%H:%M:%S:%z"`
The same can be accomplished via printf -v
by wrapping the desired format in %(...)T
, eg:
printf -v logdt '%(%Y-%m-%dT%H:%M:%S:%z)T'
NOTE: assuming %:z
should be :%z
Assuming you'll be tagging a lot of lines with datetime stamps then the savings from eliminating the subproces date
calls could be huge.
Running a test of 1000 datetime stamp generations:
$ time for ((i=1;i<=1000;i )); do { printf -v logdt '%(...)T' | logdate=$(date ...) }; done
Timings for printf -v logdt '%(...)T'
:
real 0m0.182s # ~130 times faster than $(date ...)
user 0m0.171s
sys 0m0.000s
Timings for logdt=$(date ...)
:
real 0m24.443s # ~130 times slower than printf -v
user 0m5.533s
sys 0m16.724s
CodePudding user response:
This can help you:
#!/bin/bash
echo "script started at $(date '%Y-%m-%dT%H:%M:%S%:z')"
echo "doing something"
sleep 2
echo "script finished at $(date '%Y-%m-%dT%H:%M:%S%:z')"
You might want to create an alias if calling the full command looks clumsy to you.