1

I am new to Bash so please help me articulate this question better if need be.

Let's say I have a .sh script. This script performs some calculation on some data for each day of the previous week from Sunday through Saturday (the week starts on Sunday). For e.g. Today, I am running this script for data starting 23rd Feb 2020 through 29th Feb 2020. When running the script on my terminal, I provide 3 parameters- year, month and day

./scriptname.sh ${yyyy} ${mm} ${dd} 

Now, most of the time, I am fine with something like this

yyyy=2020; mm=02; for dd in seq 23 -w 29; do ./scriptname.sh ${yyyy} ${mm} ${dd}; done 

But almost every month there is a week that spills over to the next month (e.g the week running from 29th March through 4th April). At first I thought I could automate this a little bit using variables

start_day=$(date -d "last-sunday -7 days" +%d); end_day=$(date -d "last-saturday" +%d); start_month=$(date -d "last-sunday -7 days" +%m); end_month=$(date -d "last-saturday" +%m); 

So the above script changes to something like this (had to exclude the backtick around seq for formatting sake)

yyyy=2020; for mm in ${start_month} ${end_month}; do for dd in seq -w ${start_day} ${end_day}; do ./scriptname.sh ${yyyy} ${mm} ${dd}; done; done 

But it creates all the permutations of dd and mm. How do I make sure I only pass these 7 relevant values for ${yyyy} ${mm} ${dd}?

2020 03 29 2020 03 30 2020 03 31 2020 04 01 2020 04 02 2020 04 03 2020 04 04 
1
  • You seem to aware of seq. Then for i in $(seq 1 5). Commented Mar 2, 2020 at 20:04

2 Answers 2

4

Don't do it yourself. Dates are tricky, months have variable number of days, etc. Your script also needs additional handling of years. Let date handle calculations with dates.

for i in {1..7}; do ./scriptname.sh $(date --date="-$i days" "+%Y %m %d"); done 

.g the week running from 29th March through 4th April

The way I would do it is to take 29th Match as number of seconds since epoch. Then add half a day so that leap seconds if any are not an isssue. Then just increment it by number of seconds in a day and use date to convert it back to a date.

then=$(date --date='2020/03/29 12:00:00' +%s); for i in {0..6}; do ./scriptname.sh $(date --date="@$((then + $i * 60 * 60 * 24))" "+%Y %m %d"); done 

Alternatively, you can do it without then variable, but you have to remember that the number +0 immediately coming after date is interpreted as timezone.

for i in {0..6}; do ./scriptname.sh $(date --date="2020/03/29 12:00:00 +0 +$i days" '+%Y %m %d'); done 

Because I like streaming-like parsing in bash, I would parse the output with xargs:

seq 6 | xargs -I{} date -d '2020/03/29 12:00:00Z +{} days' '+%Y %m %d' | xargs -n3 ./scriptname.sh 
Sign up to request clarification or add additional context in comments.

6 Comments

I only need to supply values of year month and day so I like the first approach better. As is, it's passing a date range from 2020 02 24 to 2020 03 01. What I need is 2020 02 23 to 2020 02 29 (the range of the previous week) How do I modify it?
The 3rd code snippet is not that hard to follow. {0..6} is the range whereas 2020/03/29 is current date and +$i days tells will be traveling forward (as opposed to -$i days).. You want for i in {0..6}; do echo $(date --date="2020/02/29 12:00:00+0 -$i days" '+%Y %m %d'); done? Or for i in {0..6}; do echo $(date --date="2020/02/23 12:00:00+0 +$i days" '+%Y %m %d'); done?
Okay that does give me the expected output I want but looks like I have to manually specify today's date. Correct?
? I do not fully understand. You have specify one date, at least. The date you start from. Or the date you end on. The interval you specified always to be 7 days. You want for i in {1..7}; do echo $(date --date="last-sunday -$i days" "+%Y %m %d"); done? Really, the date specifying string for GNU date is very... flexible.
Yes it can be modified. See my previous comment. Here (where I live) weeks start with monday: for i in {0..6}; do echo $(date --date="last-monday +$i days" "+%Y %m %d %A"); done ; )
|
1

Another example, calculating days using seconds:

for s in $(seq $(date -d "last-sunday -7 days" +%s) 86400 $(date -d "last-sunday" +%s)); do date --date=@$s "+%Y %m %d"; done 

1 Comment

Had to change the 2nd "last-sunday" to "last-saturday" but I like this approach too.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.