0

In bash, I want to filter the list of file names to .csv only, sort according to date order (the date in the name, not the timestamp), and then return the most recent file name based on date order in the name:

[root@server test2]# curl -l "ftp.fakeurl.com.au/In Stock Daily CSV/"  --user username:password
InStockDaily01.07.19.csv
InStockDaily01.07.19.xls
InStockDaily02.07.19.csv
InStockDaily02.07.19.xls
InStockDaily03.06.19.csv
InStockDaily03.06.19.xls
InStockDaily03.07.19.csv
InStockDaily03.07.19.xls
InStockDaily04.06.19.csv
InStockDaily04.06.19.xls
InStockDaily04.07.19.csv
InStockDaily04.07.19.xls
InStockDaily05.06.19.csv
InStockDaily05.06.19.xls
InStockDaily05.07.19.csv
InStockDaily05.07.19.xls
InStockDaily06.06.19.csv
InStockDaily06.06.19.xls
InStockDaily07.06.19.csv
InStockDaily07.06.19.xls
InStockDaily08.07.19.csv
InStockDaily08.07.19.xlsx
InStockDaily09.07.19.csv
InStockDaily09.07.19.xls
InStockDaily10.07.19.csv
InStockDaily10.07.19.xls
InStockDaily11.06.19.csv
1
  • next time use ISO8601 date format instead of little-endian.
    – Jasen
    Jul 28 '19 at 7:19
2

Try this:

curl -l "ftp.fakeurl.com.au/In Stock Daily CSV/"  --user username:password |
  grep '\.csv$' |
  sort -t. -k3,3 -k2,2 -k1,1 |
  tail -n 1
  • grep '\.csv$' get the csv lines
  • sort -t. -k3,3 -k2,2 -k1,1 sort using the . as field separator by 3rd field year, 2nd field month and 1st field InStockDailyXX with the day
  • tail -n 1 get the last line (newest date)
4
  • Thanks, it works - could you kindly indulge a novice so as to explain the sort -t. -k3,3 -k2,2 -k1,1 notation/structure? I've never seen that before, thanks.
    – ptrcao
    Jul 28 '19 at 1:10
  • 1
    The -t. splits the line into 4 fields by . (default is the space or the tab character) and with -k startpos[,endpos] you can set the start and optional end position of the field (it's called key in the manual). Obviously if no key is given the whole line is used as key. See the online manual, there are a few examples.
    – Freddy
    Jul 28 '19 at 1:25
  • I thank you for the kind explanation, the reference link, and the answer.
    – ptrcao
    Jul 28 '19 at 1:28
  • (Re: your previous comment) Note that the default separator is the transition from a non-blank to a blank (not limited to space and tab) Jul 28 '19 at 7:26
0

In zsh, you can get the sorted list of csvs with:

list=(*.csv(oe'<REPLY=${(j::)${(s:.:Oa)REPLY}}>'))

And then the latest one is in $list[-1]

  • *.csv(glob-qualifier): glob with glob qualifiers
  • oe'<code>': order the list based on the evaluation of the code (where the code sets the $REPLY variable as the basis for sorting)
  • ${(s:.:Oa)REPLY}: ssplit the $REPLY variable (which contains the filename to consider) on dot, and reverse Order by array indice (reverse the list) ${(j::)list}: join the elements of the list. So if $REPLY was initially InStockDaily10.07.19.csv, the new $REPLY which the glob will sort on is csv1907InStockDaily10.

That assumes the prefix is always the same as in your example. If not, you can use:

list=(*.csv(oe'<REPLY=${(j::)${(Oas:.:M)REPLY%??.??.??.*}}>'))

Where %pattern in combination with the M parameter expansion flag, extracts the suffix Matching the pattern from the end of $REPLY (so $REPLY will be csv190710 instead of csv1907InStockDaily10).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.