Bash date query stopped working - bash

A few months ago I wrote a some bash to get dates. I needed these dates as facts in an ansible script to later use them to get data from the database. This worked fine until today here is the code:
- name: Set date variables
set_fact:
first_day_last_month: "{{lookup('pipe','date -d \"-1 month -$(($(date +%d)-1)) days\" +%Y-%m-%d')}}"
last_day_last_month: "{{lookup('pipe','date -d \"$(date +%Y-%m-01) -1 day\" +%Y-%m-%d')}}"
first_day_current_month: "{{lookup('pipe','date -d \"-$(($(date +%d)-1)) days\" +%Y-%m-%d')}}"
last_day_current_month: "{{lookup('pipe','date -d \"-$(date +%d) days +1 month\" +%Y-%m-%d')}}"
However when I run this now I get an error:
/bin/sh: 1: arithmetic expression: expecting EOF: "08-1"
I tried debugging it on the bash command line:
seven#monstermachine:~$ echo $(date -d "-$($(date +%d)-1)")
08-1: command not found
Mit Nov 8 00:00:00 CET 2017
but until now i'm not getting it fixed.
Anyone have any idea?

%d is zero padded which gives base eight or octal number and 08 is not a valid octal number which thows an error.
What you need is something like :
echo $(date -d "$(($(date +%e)-1))")
Wed Nov 8 07:00:00 IST 2017
Note %e will cause date to be space padded which is equivalent to %_d.
To perform a mathematical expression use $(( expression )) format. I didn't understand the actual logic behind your code, so make sure your code fits the logic.

To get first_day_current_month in your script, you could use:
date +%Y-%m-01
similar for the others, for example to get last_day_last_month:
date -d `date +%Y-%m-01`"-1 day" +%Y-%m-%d

Thanks for the help I will make use of both of your answers to come up with a better working command.

Related

Base error when trying to get week number

I'm trying to get the week number of last week. The following command normally had work, but now I'm getting error.
lastweeknumber=$((`date +%V`-1))
bash: 09: value too great for base (error token is "09")
This week number is 09, so I've tried to convert to decimal adding 10# like this $(10#(date +%V)) but it's not working.
How to fix this?
Consider the following, which uses bash's built-in functionality in place of the external date command, and thus requires a recent shell release but is much faster to run (and will behave consistently without depending on a specific version of date).
With that done, though, there's still a need to strip the leading 0 -- which a parameter expansion will do just fine:
printf -v seconds_now '%(%s)T' -1
printf -v weeknum_lastweek '%(%V)T' "$(( seconds_now - (60 * 60 * 24 * 7) ))"
echo "The index of last week is ${weeknum_lastweek#0}"
It is because date +%V returns 09 and shell is interpreting any value starting with 0 as an octal number. Note that 09 is an invalid octal number hence you get that error value too great for base.
You can just force module 10 arithmetic in (( ... )):
echo $(( 10#$(date +%V) - 1 ))
8
Another way that handles wrapping around year correctly:
lastweeknumber=$(date -d "1 week ago" +%V)

Unix shell script Date format

I'm looking for a Date for like Mar 1 (i.e. space+padded space of day of month)
This is giving correct format => Mar 1
date -d "yesterday 13:00" +"%b %e"
However, when I try to put into a variable, the extra added space is missing.
DATE=`date -d "yesterday 13:00" +"%b %e"`
echo $DATE gives=> Mar 1 (only padded space getting)
Any idea how to get that => Mar 1 (i.e. space+padded space of day of month)
For lots of details, see When to wrap quotes around a shell variable? or I just assigned a variable, but echo $variable shows something else
Basically, you need to quote your variable when you use it:
echo "$DATE"

Using quotes within command substitution

I don't understand why this works
dateCMD=$(date -d "4 hours ago")
echo $dateCMD
Tue Oct 18 02:20:34 AEDT 2016
and this works
dateCMD="date"
$dateCMD
Tue Oct 18 06:23:19 AEDT 2016
But not this
dateCMD='date -d "4 hours ago"'
$($dateCMD)
date: extra operand ‘ago"’
How can I get this last case to work?
Short answer: you don't want to do that. Use a function instead.
dateCMD () {
date -d "4 hours ago"
}
dateCMD
Long answer: quotes in the value of a parameter are not "syntactic" quotes; they are just regular data. When you write
dateCMD='date -d "4 hours ago"'
$($dateCMD)
It is evaluated as follows:
$dateCMD expands to date -d "4 hours ago"
The expansion is split into the words date, -d, "4, hours, and ago". The quotes are not treated specially.
The first word, date, is treated as the command with the rest of the words passed as distinct arguments.
date treates "4 as the argument to the -d option. Since date takes only one additional positional argument (the format string), it takes hours as that argument, then complains that ago is an extra operand.
Use BASH array to make it work:
dateCMD=(date -d "4 hours ago")
"${dateCMD[#]}"
Mon Oct 17 11:38:54 EDT 2016
I was typing explanation on your quoting problem but then I noticed very well explained answer from #chepner so avoided adding redundant information in my answer.
To get the last case to work, you can use eval
Of course you should not use eval on any user input without completely validating that input.
dateCMD='date -d "4 hours ago"'
eval $dateCMD

Using a different date in a shell script

SO, I have a whole script that runs every hour with a date as input. Normally, it takes the current time, but now I need it to run for an interval of time in the past, every hour as well.
What I've done so far is:
DEFINING THE OLD DATE
8 start_date=20131218
9 num_hours=5
10 for i in `seq 1 $num_hours`
11 do
12 date=`date -d "${start_date}+${i} hours"`
13 echo $date # Use this however you want!
14
.
.
.
25 done
The starting date is Dec 18, 2013 and then in each iteration it should give me one more hours from the starting time. This part I found it in another article here and it works. The problem comes when I do
echo $(date)
it prints the current time instead of the time that I previously defined. Of course any other variable that I define from the date has the values from the current time. For instance,
18 datestamp=$(date +%F)
19 hourstamp=$(date +%H)
I'm new in shell programming and I have no idea what to do. Any help?
Thanks in advance.
What you want is this:
18 datestamp=$(date -d "${start_date}+${i} hours" +%F)
19 hourstamp=$(date -d "${start_date}+${i} hours" +%H)
As #BMW said, try to avoid use the date as a variable name to avoid ambiguity.
$(date) will run the command date and export the result.
so when echo it, it will return current date/time.
Second, date is the unix command, avoid to use it as a variable. so this will fix your issue"
DATE=`date -d "${start_date}+${i} hours"`
echo $DATE

Getting date of X days ago in bash script, using argument variable

I'm trying to calculate the date for a dynamic number of days ago in a bash script.
This is what I've done -
#!/bin/bash
STAMP=`date --date='$1 day ago' +%y%m%d`
but when running myscript 2, it says -
date: invalid date `$1 day ago'
How can I use my argument value in this formula?
It works if ' is replaced with " into this command on the script -
STAMP=`date --date="$1 day ago" +%y%m%d`
The clue was the two different character ` and ' used in the error response -
date: invalid date `$1 day ago'
An expert in bash scripting (not me) can probably explain why this has happen.
It's because variable substitution wouldn't happen in single quotes, i.e. '$1' wouldn't expand but "$1" would.
As such, saying
STAMP=`date --date="$1 day ago" +%y%m%d`
or
STAMP=$(date --date="$1 day ago" +%y%m%d)
would work.

Resources