Home > Mobile >  Date command as a variable in a bash script. Needs to be invoked each time instead of during variabl
Date command as a variable in a bash script. Needs to be invoked each time instead of during variabl

Time:04-26

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.

  • Related