On Tue, Dec 22, 2015 at 04:04:16AM +0100, Ángel González wrote: > Aren't you making things more complex than needed, with so much pipes > and awk? > > date(1) is your friend: > > For instance: > $ for y in {1900..2199} ; do echo -n "$y "; for m in {1..12}; do date +%A -d > $y-$m-13; done | grep -c Friday ; done > > shows there are between 1 and 3 Fridays per year.
This is the most obvious approach, but it does a fair amount of forking. Also, you're relying on GNU date. There's no portable way to do simple date lookups in a shell script, unfortunately. A pure-bash approach that avoids forking might look something like: t=946702800 # Start at Sat Jan 1 12:00:00 EST 2000 endyear=2036 while true; do printf -v year '%(%Y)T' "$t" ((year > endyear)) && break printf -v day '%(%d)T' "$t" printf -v dow '%(%w)T' "$t" if [[ $day = 13 && $dow = 5 ]]; then printf -v month '%(%m)T' "$t" echo "$year-$month-$day" fi ((t += 86400)) done But just because it doesn't fork, doesn't mean it's *fast*. Bash is so slow at everything. :( Your one-fork-per-month loop (plus one fork per year) might end up being much faster than my zero-forks-per-day loop. Mine is portable, though.