Bash Display First Friday of the next month

Hello,

I need to find the date of next first Friday of the month and set as a variable in a bash script

ie -

FIRSTFRIDAY=$(date -dfirst-friday +%d)    

I know date -dfirst-friday doesn't work, but unsure if I can use this / cal + awk or something else to find the right date of the following first Friday

Thanks in advance

Welcome to the forum.

Ususally the search function gives you a good starting point, e.g. how far would this thread get you?

Or, look at the links at this page's bottom left under "More UNIX and Linux Forum Topics You Might Find Helpful"

Hi RudiC,

I tried searching the forums and I have been searching google for a quiet a period of time with no luck - I am confused the thread you linked seems to show date + number of days? where I need to find specifically the first Friday of next month.

I found a similar answer but unsure how to make First instead of last

date +"$(cal -N |awk '/^Fr/ {print $(NF)}') %B"

from linuxquestions.org/questions/linux-general-1/how-to-find-display-out-last-friday's-date-of-the-month-4175454956/

Funny you spent so much time searching...
Looking at the first suggestion beneath ( as already suggested...) gave me an answer. so less than 5 minutes... OK in ksh but gives you and idea...

What did not say why bash, and on what OS / version you are running or did I miss it?

I wish to avoid installing additional software if there is something native that can be used ie date / cal

ksh is not available /bin/ksh: bad interpreter: No such file or directory

Operating system is Ubuntu 16.04.3 LTS

Using bash to insert this into an already existing bash script.

thanks

You haven't told us what version of bash you're using...

The following works at least with ksh version 93u+ and later versions. I believe it will also work unchanged with a recent release of bash :

if [ $# -eq 2 ]
then	MONTH=$1
	YEAR=$2
else	read MONTH YEAR <<-EOF
		$(printf '%(%m %Y)T')
EOF
fi

for((i = 1; i <= 12; i++))
do
	read MONTH YEAR <<-EOF
		$(printf '%(%m %Y)T' "$MONTH/01/$YEAR next month")
EOF
	DOW1ST=$(printf '%(%u)T' "$MONTH/01/$YEAR")
	if [ $DOW1ST -eq 5 ]
	then	FIRSTFRIDAY=01
	else	FIRSTFRIDAY=0$(((13 - DOW1ST) % 7))
		[ $FIRSTFRIDAY = "00" ] && FIRSTFRIDAY=07
	fi
	printf '%s/%s/%s\n' "$MONTH" "$FIRSTFRIDAY" "$YEAR"
done

If you invoke it without arguments it will give you the 1st Friday of each month for the next year. For instance, when I run it today, it prints:

01/05/2018
02/02/2018
03/02/2018
04/06/2018
05/04/2018
06/01/2018
07/06/2018
08/03/2018
09/07/2018
10/05/2018
11/02/2018
12/07/2018

If you invoke it with two arguments specifying a month and a year, it will give you the 1st Fridays for the year following that month and year. For example:

ksh ./tester 6 2016

prints:

07/01/2016
08/05/2016
09/02/2016
10/07/2016
11/04/2016
12/02/2016
01/06/2017
02/03/2017
03/03/2017
04/07/2017
05/05/2017
06/02/2017

If that doesn't work with your version of bash , the following should come close to working for you, but is totally untested (since I don't have access to the GNU date utility):

if [ $# -eq 2 ]
then	MONTH=$1
	YEAR=$2
else	read MONTH YEAR <<-EOF
		$(date '+%m %Y')
EOF
fi

for((i = 1; i <= 12; i++))
do
	read MONTH YEAR <<-EOF
		$(date -d "$MONTH/01/$YEAR next month" '+%m %Y')
EOF
	DOW1ST=$(date -d "$MONTH/01/$YEAR" +%u)
	if [ $DOW1ST -eq 5 ]
	then	FIRSTFRIDAY=01
	else	FIRSTFRIDAY=0$(((13 - DOW1ST) % 7))
		[ $FIRSTFRIDAY = "00" ] && FIRSTFRIDAY=07
	fi
	printf '%s/%s/%s\n' "$MONTH" "$FIRSTFRIDAY" "$YEAR"
done

I assume that you'll be able to simplify either of these scripts to get what you want.

year=2018
for month in {1..12}
do
    cal $month $year |awk -v month=$month -v year=$year '/Fr/{getline;if(NF==1){getline;}printf("%02d/%02d/%04d\n",month,$(NF-1),year);}'
done

output:

01/05/2018
02/02/2018
03/02/2018
04/06/2018
05/04/2018
06/01/2018
07/06/2018
08/03/2018
09/07/2018
10/05/2018
11/02/2018
12/07/2018

Bash/Gnu Date version

offsets=(5 4 3 2 1 0 6)
year=2018
for month in {01..12}
do
   date +"%m/%d/%Y" --date "$year/$month/01 + ${offsets[$(date +%w --date ${year}/${month}/01)]} days"
done
01/05/2018
02/02/2018
03/02/2018
04/06/2018
05/04/2018
06/01/2018
07/06/2018
08/03/2018
09/07/2018
10/05/2018
11/02/2018
12/07/2018

Of course, the disadvantage of my solution is that you are running date twice.
Or:

starts=(6 5 4 3 2 1 7)
year=2018
for month in {01..12}
do
    dstart=$(date +%w --date "$year/$month/01")
    printf "%02d/%02d/%d\n" ${month#0} ${starts[$dstart]} $year
done

Andrew