Home > Back-end >  How to sort a list of different filenames sorting a number in the filename with bash to find the &qu
How to sort a list of different filenames sorting a number in the filename with bash to find the &qu

Time:10-27

I run a command, getFiles, that outputs a newline delimited list filenames. Very similar to the output of ls -1. The filenames all end in a number representing a kind of timestamp. Larger numbers are more recent. The filenames follow no pattern. e.g. file1234, other44234, something34142, carrot123.

I need to find the filename with the largest number (numerically). In this example other44234.

After finding the filename I need to pass it as an argument into another command. i.e. doItToIt "$THE_FILE"

CodePudding user response:

Setup:

$ cat files.txt
file1234
other44234
something34142
carrot123

One convoluted chain of commands:

$ sed -nE 's/^(.*[^0-9])([0-9] )$/\2 \1\2/p' files.txt | sort -nr | head -1 | awk '{print $2}'
other44234

But once we pull awk into the mix there's really no need for anything else, eg:

awk '{ if (match($0,/([0-9] )$/)) {      # if we find a string of numbers at the end of the line (aka filename)
           sfx=substr($0,RSTART)         # strip off the number and ...
           if (sfx>max) {                # if larger than the previous find then ...
              max=sfx                    # make note of the new largest number and ...
              fname=$0                   # grab copy of current line (aka filename)
           }
       }
    }
END { if (fname) print fname}        # if fname is non-blank then print to stdout
' files.txt

This also generates:

other44234

Or doing the whole thing in bash with a regex and the BASH_REMATCH[] array:

regex="^.*[^0-9]([0-9] )$"

fname=""
max=0

while read -r f
do 
    [[ "${f}" =~ $regex ]]                  && 
    [[ "${BASH_REMATCH[1]}" -gt "${max}" ]] && 
    max="${BASH_REMATCH[1]}"                && 
    fname="${f}"
done < files.txt

This generates:

$ typeset -p fname
declare -- fname="other44234"

CodePudding user response:

You're looking for something like this:

awk '{
  tag = $0
  sub(/^.*[^0-9]/, "", tag)

  if (tag > max) {
    max = tag
    name = $0
  }
}
END {
  print name
}'

CodePudding user response:

Another way:

$ sed -E 's/^([a-Z] )([0-9] )/\1 \2/' files.txt |
    sort -n -k2 |
    tail -n1 |
    tr -d ' '

other44234

CodePudding user response:

In pure bash:

#!/bin/bash

maxnum=-1
while IFS= read -r fname; do
    n=${fname##*[!0-9]}
    if ((n > maxnum)); then
        maxnum=$n
        maxfile=$fname
    fi
done < <(getFiles)

doItToIt "$maxfile"
  • Related