List files sorted numerically

I have a bunch of files from log1 to log164.

I’m trying to LIST the directory (sorted) in a UNIX terminal but the sort functions are only providing the format like this:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

What I want is

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Any suggestions in what I could use to do this?

Asked By: Rabiani

||

bash‘s braces, {}, will enumerate them in order:

for file in log{1..164}.gz; do
    process "$file"
done
Answered By: Kevin

Perl solution:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(d+).gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'
Answered By: Barton Chittenden

Why not use the built-in GNU ls feature for this particular case:

-v — natural sort of (version) numbers within text

For example:

ls -1v log*
Answered By: lik

With GNU ls (i.e. on Linux, Cygwin, or other systems that have GNU ls specifically installed):

ls -v

In zsh:

echo *(n)

In other shells:

echo log?.gz log??.gz log???.gz

Replace echo by printf '%sn' if you want each file name on a separate line.

If you want file metadata as well (ls -l) and you don’t have GNU ls, you’ll need to call ls separately for each file name or group of file names that you want to see in lexicographic order.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

To avoid these difficulties, use enough leading zeroes in your file names so that the lexicographic sort is human-friendly (log001.gz, etc).

While the solution ls -1v is certainly the nicest in this particular case, I think it’s good to have also one that works with sort as in the original question, since this works also when your input does not come from ls. In this case you can use:

ls -1 | sort -n -k1.4

The -n option tells sort to sort numerically, and -k 1.4 sets the sort key to the first field (which is the whole filename in this case) starting from the 4th character up to the last.

Answered By: Elmar Zander

My version of Solaris doesn’t support ls -v (grrr). And the sort solution provided above 1) requires knowledge of the position of digits in the filename, and 2) doesn’t handle things like multi-part version numbers.

The approach below is Solaris-compatible, doesn’t require foreknowledge of the digit positions, and handles version numbers with 2, 3 or 4 components (like: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). It also uses sort -f to fold upper- and lowercase together, and properly handles directories intermixed with files:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Note that this version limits the first component to a single digit.

If your target operating system(s) supports ls -v, that is clearly the superior solution.

Answered By: MykennaC

The GNU sort (as available on Linux,) has a “version sort” mode that interprets numberes inside non-numbers just the way you ask for:

From man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Creating empty test files to list:
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz)

Your example case, adding the -V option (or --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz
Answered By: Volker Siegel
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
Answered By: kjohri

if you use Mac or BSD try this:

ls -1 *.jpg | sort -n
Answered By: Salvador Almaraz

This worked for me.

I have files 1.jpg 2.jpg … 18.jpg

$ echo *.jpg | tr -s ' ' 'n' | sort -n

sort is getting confused with ls output because of unprintable colour characters. If you try this:

ls -1 --color=none *.jpg | sort -n

it will work perfectly.

sort can ignore unprintable characters with -i option but it still doesn’t work and I don’t know why.

But you can always strip colour like this and sort will work:

ls -1 --color=always *.jpg | sed -r "s/x1B[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

I hope one day sort will have an option for this.

Answered By: Dmitry

Command:

ls -l | sort --human-numeric-sort
Answered By: shayar hashim
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.