Goal
I have a series of files that have various names. Each file's name contain a unique integer number made of between 1 and 4 digits. I would like to order the files (by displaying their full name) but ordered by the number they contain.
Example
The files ..
Hello54.txt
piou2piou.txt
hap_1002_py.txt
JustAFile_78.txt
darwin2012.txt
.. should be listed as
piou2piou.txt
Hello54.txt
JustAFile_78.txt
hap_1002_py.txt
darwin2012.txt
You just need to sort by the numeric part. One approach might be to eliminate the non-numeric part and build an array. On the upside, bash has sparse arrays, so whatever order you add the members in, they will come out in the correct order. Pseudo code:
array[name_with_non_numerics_stripped]=name
print array
My quick and not careful implementation:
sortnum() {
# Store the output in a sparse array to get implicit sorting
local -a map
local key
# (REPLY is the default name `read` reads into.)
local REPLY
while read -r; do
# Substitution parameter expansion to nuke non-numeric chars
key="${REPLY//[^0-9]}"
# If key occurs more than once, you will lose a member.
map[key]="$REPLY"
done
# Split output by newlines.
local IFS=$'\n'
echo "${map[*]}"
}
If you have two members with the same "numeric" value, only the last one will be printed. @BenjaminW suggested appending such entries together with a newline. Something like…
[[ ${map[key]} ]] && map[key]+=$'\n'
map[key]+="$REPLY"
…in place of the map[key]="$REPLY"
above.