Reputation: 557
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
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
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
Reputation: 1831
Try ls -1 | sort -t _ -k1.5,1n
this sort on the 5th character forward.
Upvotes: 0
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