Unix shell scripting: date format syntax - shell

I m trying to get yesterday date, it's not working in hp ux server.
Prev_date=$(date +"y%m%d" -d "1 day ago")
For this I m still getting current date only.
20210811
Could you please help on the same.

You missed a percentage in front of the 'y': this is working fine for me:
echo $(date +"%y%m%d" -d "1 day ago")

You can use below command, if you want.
date --date=' 1 days ago' '+%Y-%m-%d'
It will give result like
2021-09-06
I prefer this format since most of the time my scripts include SQL queries for data fetch and hence date is required to filter out data on daily basis.

Related

How to get last Week's date in bash SunOS

Here is my issue: I have a backup bash script that needs to access a folder with a date in its name for example : backup_01072022 .
I used date=`TZ=GMT+24 date +%d%m%Y` when i needed to access the backup folder of yesterday.
Now I want to access the backup folder of last week :
date=`TZ=GMT+168 date +%d%m%Y` , it doesn't work , it show today's date.
I read that TZ doesn't work for a value above +144.
Is there any other way of manipulating dates in SunOS 6.8 ?
Notes :
SunOS 6.8
version of the date util : 8.5
version of bash : 4.1.11(2)-release
This'll depend on the version of date on your system.
With GNU date (v 8.26):
$ TZ=GMT date '+%d%m%Y'
06072022 # today
$ TZ=GMT date '+%d%m%Y' -d 'last week'
29062022
$ TZ=GMT date '+%d%m%Y' -d '7 days ago'
29062022
NOTE: I'll leave it up to OP to determine if the explicit TZ setting should be adjusted (or used at all)
I seem to recall SunOS comes with Perl, so if you don't have a date that supports --date="...", you should be able to do:
date=$(perl -MPOSIX -e '
print POSIX::strftime "%d%m%Y", localtime time-(60*60*24*7)
')
Thanks to the helpful commments and answers I was able to make it work using :
/usr/gnu/bin/date -d "last week" '+%d%m%Y'
It turns out I was not using the GNU date util until I specified it explicitly, and that's neither --date nor -d was working for me.
I still can't figure out what date util I was using by default if not GNU date.

Why do I always get extra one day with date difference in bash?

I'm trying to calculate the seconds between a date from now, however, I always get extra one day when adding the seconds from now.
echo $(($(date -ud "2020-03-15 19:13" +'%s') - $(date +'%s')))
As of posting, the result is 1744204
Using this website to check, I gets 16 March, not 15 March as expected. Any idea why?
verify the result of your date commands and verify the timezone of both.
The first result of the command shows the timestamp in UTC, and the second one shows the timestamp using the timezone of the system.
Here is the difference:
$ date -ud "2020-03-15 19:13" +'%s'
1584299580
With UTC-3 in my system:
$ date -d "2020-03-15 19:13" +'%s'
1584310380
I hope that help you.

Why is the date command throwing an error despite successfully computing an answer?

For context I am working on a Windows machine with MINGW64. I have not had the chance to test this on a machine running Linux.
I am working with [date][1] in bash and trying to add days to a date represented as seconds since 1970-01-01 00:00:00, i.e. in format %s. I have the following Bash code:
DATE1=$(date --date=now "+%s")
echo "DATE1: ${DATE1}"
DATE2=$(date --date="$(date --date="${DATE1}" "+%s")+2 days" "+%d%b%Y %H:%M:%S")
echo "DATE2: ${DATE2}"
Which gives console output
DATE1: 156133763
date: invalid date '1561337963'
DATE2: 26Jun2019 10:59:24
In fact, DATE2 has the expected value down to the second. However the console still throws an error. Why might this error be occurring? Would it have something to do with running MINGW64?
An update:
I ran this on a Debian server I have access to. It computed the time with now like on MINGW, but returned a different error: ./test.sh: line 3: --date=1561342165: command not found.
Running this on the same server with a custom date:
DATE1=$(date --date="$(date --date="19Jun2019 11:35:46" "+%d%b%Y %H:%M:%S")" "+%s")
Likewise returns
DATE1: 1560908146
date: invalid date ‘1560908146’
DATE2: 26Jun2019 12:20:08
Which actually indicates it isn't adding to the defined date at all, rather it is just adding to today's date (it's the 24th of June where I am now). Clearly, something is quite wrong!
If you want to convert timestamp to a date then you have to use #:
date --date=#1561344591 '+%F %T'
2019-06-24 04:49:51
The reason why you got seemingly correct result even with the error message is because your DATE1 is now, so your inner date call produces an error and returns nothing and then the outer call is just --date=+2 days, which produces 2 days from now.
I don't think you can use date-time in timestamp format together with relative statements, it doesn't work even with #. You have to convert your timestamp to human readable date first but even then you have to be careful. You could think that this is enough:
date --date="$(date --date=#1561344591 "+%F %T") + 2 days" "+%F %T"
2019-06-25 04:49:51
As you can see it is still wrong and that's because +2 is parsed as a timezone. You fix it by explicitly including timezone in you conversion from timestamp:
date --date="$(date --date=#1561344591 "+%F %T%Z") + 2 days" "+%F %T"
2019-06-26 04:49:51
In general, using bash debugging set -x and date debugging date --debug ... helps with solving such problems.

Bash scripting: date -d won't accept my string format of hhmmss. I need a workaround

I need a Bash script to accept 1 argument representing a time in hhmmss format, and from that derive a second time 3 minutes before that.
I've been trying to use date -d:
#! /bin/bash
DATE=`date +%Y%m%d`
TIME=$1
NEWTIME=`date -d "$DATE $TIME - 3 minutes" +%H%M%S`
echo $NEWTIME
In action:
$ ./myscript.sh 123456
invalid date `20141022 123456 - 3 minutes'
It seems the problem is with the 6 character time format because 4 characters (eg 1234) works. The subtraction of the 3 minutes is not the problem because I get the same error when I remove it.
It has occurred to me I could parse the time into a more palatable format before sending it to date. I tried inserting delimiters by adding this line:
TIME=${TIME:0:2}:${TIME:2:2}:${TIME:4:2}
It accepted that format but the answer to the - 3 minutes part was inexplicably very wrong (it subtracted 2 hours and 1 minute):
$ ./myscript.sh 123456
103356
Vexing.
It has also occurred to me that I might be able to provide date with an input format, like strptime which I'm familiar with from Python. I've found references to strptime in the context of Bash but I've been unable to get it to do anything.
Does anyone have any suggestions on getting the hhmmss time-string to work? Any help is much appreciated.
FYI: I'm trying to avoid changing the 6 character input format because that would involve changing other scripts as well as getting certain human users to alter long-entrenched habits. I'm also trying to avoid outsourcing this task to another language. (I could easily do this in Python). I want a Bash solution to this problem, if there is one.
TIME=093000
TIME=${TIME:0:2}:${TIME:2:2}:${TIME:4:2} # your line
date -d "2014-10-20 $TIME 3 mins ago" +%H%M%S
Output:
092700

Text-Message Gateways & Incrementing Bash Variable Daily

I have a bash script that is sending me a text daily, for 100 days.
#! /bin/bash
EMAIL="my-phone-gateway#address.net"
MESSAGE="message_content.txt"
mail $EMAIL < $MESSAGE
Using crontab, I can have the static $MESSAGE sent to me every day.
Other than hard-coding 100 days of texts ;)
How could I implement a variable counter such that I can have my texts say:
"Today is Day #1" on the first day, "Today is Day #2" on the second day, etc. ?
Note: The location of the requested text within the $MESSAGE file doesn't matter. Last line, first line, middle, etc.
The only requirement for an answer here is that I know what day it is relative to the first, where the first day is the day the script was started.
Of course, bonus awesome points for the cleanest, simplest, shortest solution :)
For our nightly build systems, I wrote a C program that does the calculation (using local proprietary libraries that store dates as a number of days since a reference date). Basically, given a (non-changing) reference date, it reports the number of days since the reference date. So, the cron script would have a hard-wired first day in it, and the program would report the number of days since then.
The big advantage of this system is that the reference date doesn't change (very often), so the script doesn't change (very often), and there are no external files to store information in.
There probably are ways to achieve the same effect with standard Unix tools, but I've not sat down and worked out the portable solution. I'd probably think it terms of using Perl. (The C program only works up to 2999 CE; I left a note in the code for people to contact me about 50 years before it becomes a problem for the Y3K fix. It is probably trivial.)
You could perhaps work in terms of Unix timestamps...
Create a script 'days_since 1234567890' which treats the number as the reference date, gets the current time stamp (from date with appropriate format specification; on Linux, date '+%s' would do that job, and it works on Mac OS X too), takes the difference and divides by 86,400 (the number of seconds in a day).
refdate=1234567890
bc <<EOF
scale=0
($(date '+%s') - $refdate) / 86400
EOF
An example:
$ timestamp 1234567890
1234567890 = Fri Feb 13 15:31:30 2009
$ timestamp
1330027280 = Thu Feb 23 12:01:20 2012
$ refdate=1234567890
$ bc <<EOF
> scale=0
> ($(date '+%s') - $refdate) / 86400
> EOF
1104
$
So, if the reference date was 13th Feb 2009, today is day 1104. (The program bc is the calculator; its name has nothing to do with Anno Domini or Before Christ. The program timestamp is another homebrew of mine that prints timestamps according to a format that can be specified; it is a specialized variant of date originally written in the days before date had the functionality, by which I mean in the early 1980s.)
In a Perl one-liner (assuming you specify the reference date in your script):
perl -e 'printf "%d\n", int((time - 1234567890)/ 86400)'
or:
days=$(perl -e 'printf "%d\n", int((time - 1234567890)/ 86400)')
The only way to accomplish this would be to store the date in a file, and read from that file each day. I would suggest storing the epoch time.
today=$(date +%s)
time_file="~/.first_time"
if [[ -f $time_file ]]; then
f_time=$(< "$time_file")
else
f_time=$today
echo "$f_time" > "$time_file"
fi
printf 'This is day: %s\n' "$((($today - $f_time) / 60 / 60 / 24))"
Considering that your script is running only once a day, something like this should work:
#!/bin/bash
EMAIL="my-phone-gateway#address.net"
MESSAGE="message_content.txt"
STFILE=/tmp/start.txt
start=0
[ -f $STFILE ] && start=$(<$STFILE)
start=$((start+1))
MESSAGE=${MESSAGE}$'\n'"Today is Day #${start}"
echo "$start" > $STFILE
mail $EMAIL < $MESSAGE
A simple answer would be to export the current value to an external file, and read that back in again later.
So, for example, make a file called "CurrentDay.dat" that has the number 1 in it.
Then, in your bash script, read in the number and increment it.
e.g. your bash script could be:
#!/bin/bash
#Your stuff here.
DayCounter=$(<CurrentDay.dat)
#Use the value of DayCounter (i.e. $DayCounter) in your message.
DayCounter=$((DayCounter + 1))
echo $DayCounter > CurrentDay.dat
Of course, you may need to implement some additional checks to avoid something going wrong, but that should work as is.

Resources