echo "L_58420.K
L_58420.J
L_58420.M
L_46657.J
L_58420.N
L_58420.P
L_46657.N
L_58420.Q
L_46657.K
L_58420.O
L_46657.O
L_46657.L
L_46657.M
L_58420.L" | sed 's/[_.]/ /g' | sort -r -k 2 -k 3 | while read L no c ; do if [[ "$no" != "$last" ]]; then echo L_$no.$c; last=$no; fi; done;
L_58420.Q
L_46657.O
Sed splits the String at _ and . into pieces, so sort can sort by key 2 (number) and 3 (trailing char). A while loop reads the constant L (ignores it), a no and the c. Prints, if it is a new $no and keeps it as the new $last. In the output, we inject _ and . back again.
old solution before clarification in comment:
Pipe it through rev | sort -r | rev:
echo "L_58420.K
L_58420.J
L_58420.M
L_46657.J
L_58420.N
L_58420.P
L_46657.N
L_58420.Q
L_46657.K
L_58420.O
L_46657.O
L_46657.L
L_46657.M
L_58420.L" | rev | sort -r | rev
L_58420.Q
L_58420.P
L_46657.O
L_58420.O
L_46657.N
L_58420.N
L_46657.M
L_58420.M
L_46657.L
L_58420.L
L_46657.K
L_58420.K
L_46657.J
L_58420.J
The rev
reverses a line, sort -r
sorts reverse (descending) and again rev
brings the strings back into the right order.
To reduce the output to two lines, add a pipe | head -n 2
to the end. You can append the whole pipeline to your find command, but I didn't like to generate all that file names in a test environment. :)