2

I've got a few folders

src/1.0.0.1/
src/1.0.0.2/
src/1.0.0.12/
src/1.0.0.13/
src/1.0.1.1/

I'm looking for a bash command-chain that always returns only the latest version. In the upper case that would be 1.0.1.1. If 1.0.1.1 wasn't present the latest version would be 1.0.0.13

I'm on OS X so sort has no -V option.

Can anyone help me out here?

Hedge
  • 16,142
  • 42
  • 141
  • 246

2 Answers2

2

Use sort (the -V option performs version sort):

$ ls -1 src/
1.0.0.1
1.0.0.12
1.0.0.13
1.0.0.2
$ find src/1* -type d | sort -rV
src/1.0.0.13
src/1.0.0.12
src/1.0.0.2
src/1.0.0.1
$ mkdir src/1.0.1.1
$ find src/1* -type d | sort -rV
src/1.0.1.1
src/1.0.0.13
src/1.0.0.12
src/1.0.0.2
src/1.0.0.1

Pipe the output to head and you can get only the highest version:

$ find src/1* -type d | sort -rV | head -1
src/1.0.1.1
devnull
  • 118,548
  • 33
  • 236
  • 227
2

You can also use an awk script:

#!/usr/bin/awk -f

$0 ~ /[0-9]+(.[0-9]+)*\/?$/ {
    t = $0
    sub(/\/$/, "", t)
    sub(/.*\//, "", t)
    current_count = split(t, current_array, /\./)

    is_later = 0

    for (i = 1; i <= current_count || i <= latest_count; ++i) {
        if (current_array[i] > latest_array[i]) {
            is_later = 1
            break
        } else if (latest_array[i] > current_array[i]) {
            break
        }
    }

    if (is_later) {
        latest_string = $0
        latest_count = split(t, latest_array, /\./)
    }
}

END {
    if (latest_count) {
        print latest_string
    }
}

Run:

find src/ -maxdepth 1 -type d | awk -f script.awk  ## Or
ls -1 src/ | awk -f script.awk

You can also use a minimized version:

... | awk -- '$0~/[0-9]+(.[0-9]+)*\/?$/{t=$0;sub(/\/$/,"",t);sub(/.*\//,"",t);c=split(t,a,/\./);l=0;for(i=1;i<=c||i<=z;++i){if(a[i]>x[i]){l=1;break}else if(x[i]>a[i])break}if(l){s=$0;z=split(t,x,/\./)}}END{if(z)print s}'
konsolebox
  • 72,135
  • 12
  • 99
  • 105