Sort and list the files from a directory in numeric order

6.2k Views Asked by At

This is my folder structure.

/home/files/encounters 9-22-11-0.jpg .. /home/files/encounters 9-22-11-[n].jpg

puts Dir.glob("/home/files/*.jpg")[0] 

When i execute the above code, it displayed the sixth file (index 5 => /home/files/encounters 9-22-11-5.jpg), but actually i need the output as first file(index 0 => /home/files/encounters 9-22-11-0.jpg)

How can i sort the files as user defined sorting order?. like

When i tried..
..[0] => /home/files/encounters 9-22-11-5.jpg
..[1] => /home/files/encounters 9-22-11-21.jpg
..[2] => /home/files/encounters 9-22-11-39.jpg

But, I need
..[0] => /home/files/encounters 9-22-11-0.jpg
..[1] => /home/files/encounters 9-22-11-1.jpg
..[2] => /home/files/encounters 9-22-11-2.jpg

Additional information, sorting is also not working.

f = Dir.glob("/home/files/*.jpg").sort
f[0] => /home/files/encounters 9-22-11-0.jpg
f[0] => /home/files/encounters 9-22-11-1.jpg
f[0] => /home/files/encounters 9-22-11-10.jpg
f[0] => /home/files/encounters 9-22-11-11.jpg

2

There are 2 best solutions below

4
On
puts Dir.glob("/home/files/*.jpg").sort

Would work if you had a format like 11-09-22-05.jpg instead of 9-22-11-5.jpg. You could try to sort them as a number instead.

Dir.glob("/home/files/*.jpg").sort_by {|s| s.gsub("-","").to_i }

But as it seems you have month-day-year-number I guess that the correct way to sort is a bit more complicated than that.

arr=%w[9-22-12-33.jpg 9-22-11-5.jpg 9-22-10-99.jpg 12-24-11-1.jpg]
arr.sort_by do |s|
  t = s.split("-").map(&:to_i)
  [t[2], t[0], t[1], t[3]]
end

It works by reformatting 9-22-11-5.jpg to an array containing [11, 9, 22, 5] and then sorts by that instead.

3
On

If possible, I'd create the files with a fixed width numeric format instead:

encounters 9-22-11-05.jpg
encounters 9-22-11-11.jpg
encounters 9-22-11-99.jpg

If that's impossible, you can extract the last numeric part and use that in a custom sort criterion:

a = Dir.glob("*.jpg")
r = Regexp.new(".*-([0-9]+).jpg")
b = a.sort do |f1, f2|
  n1 = r.match(f1)[1].to_i
  n2 = r.match(f2)[1].to_i
  n1 <=> n2
end
puts b

This extracts the last numeric part from each filename (using a regular expression) and sorts by this.
If you have files belonging to different dates, you'll have to modify this so it sorts by their "base" names plus the numeric part.