Navin
Navin

Reputation: 299

list file names with sorted order - ls command

I have some files in a UNIX directory:

/opt/apps/testloc $ ls -mn 
test_1.txt
test_2.txt
test_11.txt
test_12.txt
test_3.txt

I want to list this with ls command and I need the output in sorted order based on the numbers at the end of the file name. Say output should be like below.

test_1.txt, test_2.txt, test_3.txt, test_11.txt, test_12.txt

I am not able to get as mentioned. These file names were considered as text and they were sorted as below,

test_11.txt, test_12.txt, test_1.txt, test_2.txt, test_3.txt

My command ls –mn (I need the output to be in comma separated format so I have used -m)

I need this to be done to process the files in incremental format in my next process.

Upvotes: 1

Views: 16467

Answers (4)

Andrey
Andrey

Reputation: 2583

If all the file names contain exactly one _ character, followed by a numeric value, this relatively simple script will sort file names by the numeric field and output them in a ,[space] separated list (as ls -m does):

ls -1 *_* | sort -t_ -n -k2 | sed ':0 N;s/\n/, /;t0'

However, if there are multiple _ characters in file names and you want to sort them by the last numeric field (not necessarily the same within the file names, e.g. test_1_3.txt and test_2.txt), more complex script is required:

ls -1 *_* |
awk -F '_' '
{
  key[gensub(/\..*$/, "", 1, $NF) "a" NR] = NR;
  name[NR] = $0;
}
END {
  len = asorti(key, keysorted, "@ind_num_asc");
  for (i = 1; i < len; i++) {
    printf "%s, ", name[key[keysorted[i] ] ];
  }
  printf "%s\n", name[key[keysorted[len] ] ];
}'

Upvotes: 0

ormaaj
ormaaj

Reputation: 6577

That you require output to be in a specific format tells me that you shouldn't be using ls. Since recursive results aren't required, use a glob.

# Bash or ksh + GNU or other sort that handles NUL delimiters

function sortFiles {
    [[ -e $1 ]] || return 1
    typeset a x
    for x; do
        printf '%s %s\0' "${x//[^[:digit:]]}" "$x"
    done |
    LC_ALL=C sort -nz - | {
        while IFS= read -rd '' x; do
            a+=("${x#* }")
        done
        typeset IFS=,
        printf '%s\n' "${a[*]}"
    }
}

sortFiles *

Upvotes: 1

Chris Seymour
Chris Seymour

Reputation: 85785

If you version of sort can do a version sort with -V then:

$ ls | sort -V | awk '{str=str$0", "}END{sub(/, $/,"",str);print str}'
test_1.txt, test_2.txt, test_3.txt, test_11.txt, test_12.txt

If not do:

$ ls | sort -t_ -nk2,2 | awk '{str=str$0","}END{sub(/,$/,"",str);print str}'
test_1.txt, test_2.txt, test_3.txt, test_11.txt, test_12.txt

Upvotes: 2

Yogendra Sharma
Yogendra Sharma

Reputation: 21

ls -al | sort +4n : List the files in the ascending order of the file-size. i.e sorted by 5th filed and displaying smallest files first.

Upvotes: -1

Related Questions