user1939168
user1939168

Reputation: 557

sorting list of files based upon the first numeric value

I am new to Unix. I need some help in sorting file names. I have a list of files as below:

FILE10_11_9_1_C.sql 
FILE11_11_9_1_P.sql 
LE12_11-9-1-P.sql 
FILE13_11-9-1-P.sql 
FILE14_11_9_1_P.sql 
E15_11_9_1_P.sql 
FILE16_11_9_1_P.sql 
FILE17_11_9_1_U.sql 
FILE17_11_9_1_U.sql 
FILE5_11_9_1_A.sql 
FILE7_PKG_C.sql 
FILE8_PKG_CV.sql 
Fi1_11_9_1_E.sql 
File2_11_9_1_E.sql 
File3_11_9_1_C.sql 
FILE4_11_9_1_P.sql 

I want to sort it numerically till first underscore is encountered(number can be at anyposition and not eaxct at 5th position). For ex- as below:

File1_11_9_1 
File2_11_9_1 
. 
. 
. 
File8_Pkg 
File10_11_9_1 

I am trying with ls -1|sort -t"_" -k1,4n but this does'nt seem to work.

Upvotes: 2

Views: 151

Answers (4)

Steve
Steve

Reputation: 54392

Assuming your filenames don't begin with numbers, here's one way using GNU awk. It will sort by the first number preceding an underscore, then by order of occurrence. Also generally speaking, parsing ls is a bad idea, although it would 'work' with your filenames. I prefer using GNU find. Run like:

awk -f script.awk <(find ./* -maxdepth 1 -type f -name "*.sql" -printf "%f\n")

Contents of script.awk:

BEGIN {
    FS="[^0-9]+"
}

{
    a[$2] = (a[$2] ? a[$2] ORS : "") $0
}

END {
    for (i in a) {
        b[j++]=i+0
    }

    n = asort(b)

    for (k=1;k<=n;k++) {
        print a[b[k]]
    }
}

Results:

Fi1_11_9_1_E.sql 
File2_11_9_1_E.sql 
File3_11_9_1_C.sql 
FILE4_11_9_1_P.sql 
FILE5_11_9_1_A.sql 
FILE7_PKG_C.sql 
FILE8_PKG_CV.sql 
FILE10_11_9_1_C.sql 
FILE11_11_9_1_P.sql 
LE12_11-9-1-P.sql 
FILE13_11-9-1-P.sql 
FILE14_11_9_1_P.sql 
E15_11_9_1_P.sql 
FILE16_11_9_1_P.sql 
FILE17_11_9_1_U.sql 
FILE17_11_9_1_U.sql

Alternatively, here's the one-liner:

awk -F "[^0-9]+" '{ a[$2] = (a[$2] ? a[$2] ORS : "") $0 } END { for (i in a) b[j++]=i+0; n = asort(b); for (k=1;k<=n;k++) print a[b[k]] }' <(find ./* -maxdepth 1 -type f -name "*.sql" -printf "%f\n")

Upvotes: 0

Kent
Kent

Reputation: 195039

well I am a bit lazy to remember sort fancy options.

just combine linux power text handlers to achieve it. There must be more elegant way to do that. but this is working without too much thinking

your ls...|awk -F'[Ee_]' '{print $2" "$0}'|sort -n|sed -r 's/[0-9]+ //'

EDIT

add a pure awk one-liner:

ls...|awk -F'[Ee_]' '{a[NR]=$2;b[$2]=$0;}END{n=asort(a);for(i=1;i<=n;i++)print b[a[i]]}'

works like:

kent$  echo "FILE10_11_9_1_C.sql 
FILE11_11_9_1_P.sql 
FILE12_11-9-1-P.sql 
FILE13_11-9-1-P.sql 
FILE14_11_9_1_P.sql 
FILE15_11_9_1_P.sql 
FILE16_11_9_1_P.sql 
FILE17_11_9_1_U.sql 
FILE17_11_9_1_U.sql 
FILE5_11_9_1_A.sql 
FILE7_PKG_C.sql 
FILE8_PKG_CV.sql 
File1_11_9_1_E.sql 
File2_11_9_1_E.sql 
File3_11_9_1_C.sql 
FILE4_11_9_1_P.sql"|awk -F'[Ee_]' '{print $2" "$0}'|sort -n|sed -r 's/[0-9]+ //' 
File1_11_9_1_E.sql 
File2_11_9_1_E.sql 
File3_11_9_1_C.sql 
FILE4_11_9_1_P.sql
FILE5_11_9_1_A.sql 
FILE7_PKG_C.sql 
FILE8_PKG_CV.sql 
FILE10_11_9_1_C.sql 
FILE11_11_9_1_P.sql 
FILE12_11-9-1-P.sql 
FILE13_11-9-1-P.sql 
FILE14_11_9_1_P.sql 
FILE15_11_9_1_P.sql 
FILE16_11_9_1_P.sql 
FILE17_11_9_1_U.sql 
FILE17_11_9_1_U.sql 

Upvotes: 0

Alepac
Alepac

Reputation: 1831

Try ls -1 | sort -t _ -k1.5,1n this sort on the 5th character forward.

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 203254

$ sort -k1.5n file
File1_11_9_1_E.sql
File2_11_9_1_E.sql
File3_11_9_1_C.sql
FILE4_11_9_1_P.sql
FILE5_11_9_1_A.sql
FILE7_PKG_C.sql
FILE8_PKG_CV.sql
FILE10_11_9_1_C.sql
FILE11_11_9_1_P.sql
FILE12_11-9-1-P.sql
FILE13_11-9-1-P.sql
FILE14_11_9_1_P.sql
FILE15_11_9_1_P.sql
FILE16_11_9_1_P.sql
FILE17_11_9_1_U.sql
FILE17_11_9_1_U.sql

Upvotes: 2

Related Questions