2

Could someone help me to get the file for every week using ls command?

ls -t {path} | grep -e "-1700" | head -30 | sort -r

With this ls command, I got below mentioned output

2022.05.30-1700
2022.05.28-1700
2022.05.26-1700
2022.05.25-1700
2022.05.22-1700
2022.05.21-1700
2022.05.18-1700
2022.05.17-1700
2022.05.16-1700
2022.05.15-1700
2022.05.14-1700
2022.05.13-1700
2022.05.12-1700
2022.05.09-1700
2022.05.08-1700
2022.05.02-1700
2022.04.26-1700
2022.04.24-1700
2022.04.23-1700
2022.04.21-1700
2022.04.17-1700
2022.04.16-1700
2022.02.25-1700
2022.02.19-1700
2022.02.12-1700
2022.02.11-1700
2022.01.29-1700
2022.01.23-1700
2022.01.22-1700
2022.01.15-1700

But we need only one build for every week

example like this:

2022.05.21-1700
2022.05.14-1700
2022.05.07-1700
...
...
...
2
  • 1
    2022.05.07-1700 is among your expected output, but it's not in your input. May 31, 2022 at 13:18
  • What about this?: Get the first file, remember the date (maybe via touch -r), then find the next file that is at least 7 days newer than the first one. Then repeat until there are no more files left. That procedure is assuming that a file like 2022.01.15-1700 was actually created at 17:00 on January 15th 2022, of course; actually it would work with any name then.
    – U. Windl
    May 31, 2022 at 23:33

1 Answer 1

5

Assuming you want to pick the ones from Saturdays and that you're on a GNU system, you could do:

ls {path} |
  tr .- '- ' |
  LC_ALL=C date -uf - '+%A %Y.%m.%d-%H%M' |
  grep -Po '^Saturday \K.*-1700'

With zsh (and on any system), you could do the same using a glob qualifier function:

zmodload zsh/datetime
On{Mon,Tue,Wed,Thu,Fru,Sat,Sun} () {
  local t
  TZ=UTC0 strftime -rs t %Y.%m.%d-%H%M $REPLY:t &&
    TZ=UTC0 LC_ALL=C strftime -s t %a $t &&
    [[ $0 = On$t ]]
}

and then:

print -rC1 -- <1900-2100>.<1-12>.<1-31>-1700(N+OnSat)

For the ones on Saturdays.

On your sample, they give:

2022.01.15-1700
2022.01.22-1700
2022.01.29-1700
2022.02.12-1700
2022.02.19-1700
2022.04.16-1700
2022.04.23-1700
2022.05.14-1700
2022.05.21-1700
2022.05.28-1700

You'll notice that there are some gaps, as there's not one file for every Saturday.

To get one per week (the latest of each week), where weeks run from Sunday to Saturday, you could do:

ls -r {path} |
  tr .- '- ' |
  date -uf - '+%Y%U %Y.%m.%d-%H%M' |
  uniq -w6 |
  cut -d' ' -f2

Which on your sample gives:

2022.05.30-1700
2022.05.28-1700
2022.05.21-1700
2022.05.14-1700
2022.05.02-1700
2022.04.26-1700
2022.04.23-1700
2022.04.16-1700
2022.02.25-1700
2022.02.19-1700
2022.02.12-1700
2022.01.29-1700
2022.01.22-1700
2022.01.15-1700

(not all being on Saturdays).

For weeks running from Monday to Sunday, replace %Y%U with %G%V (the ISO week year and number). That one would also work correctly around changes of years as the %G and %V only change between the 31st of December and the 1st of January if the 31st is a Sunday while %Y%U gives 202152 on Friday 2021-12-31 and 202200 on Saturday 2022-01-01 for instance.

Those are the only two options with % formatting sequences supported by date. For weeks starting on different days we'd need to be take a different approach.

For example, we could use the epoch time for the corresponding date interpreted as UTC, divided by the number of seconds in a week, properly offset for the required first day of the week which would also avoid problems around the first day of the year.

For instance, for weeks starting on Sunday:

ls -r {path} |
  tr .- '- ' |
  date -uf - '+%s %Y.%m.%d-%H%M' |
  awk '{week = int(($1 / 86400 - 3)/ 7)}
       week != last {print $2}
       {last = week}'

Replace - 3 with - 4 for weeks starting on Monday, or - 2 for weeks starting on Saturday.

Or with zsh:

zmodload zsh/datetime
typeset -A latest=()
for f (<1900-2100>.<1-12>.<1-31>-1700(N))
  TZ=UTC0 strftime -rs t %Y.%m.%d-%H%M $f &&
  latest[$(( (t / 86400 - 3) / 7 ))]=$f
print -roC1 -- $latest
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .