Forum: Ruby Show newest file in directory?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Cf63da956b6ba955687a2f2f262928cb?d=identicon&s=25 Mmcolli00 Mom (mmcolli00)
on 2008-12-18 18:44
If you have a directory full of files, how can you get the newest file
and oldest file from that directory?

require 'fileutils'
require 'find'
require 'ftools'
require 'enumerator'

Dir.entries("C:/New").each do |filename|
  NewestFile = filename.max
  OldestFile = filename.min
  puts "newest"
  puts NewestFile
  puts "oldest"
  puts OldestFile
 end
134ea397777886d6f0aa992672a50eaa?d=identicon&s=25 Mark Thomas (Guest)
on 2008-12-18 20:56
(Received via mailing list)
On Dec 18, 12:36 pm, Mmcolli00 Mom <mmc_coll...@yahoo.com> wrote:
> If you have a directory full of files, how can you get the newest file
> and oldest file from that directory?

One way...

  ages = Dir["C:/New"].map{|f| [f,File.mtime(f)] }.sort_by{|i|i[1]}

This gives you a sorted list of [filename,age] pairs. Then you can do
this:

  newest, oldest = ages[0][0], ages[-1][0]


Or, if you want it in one fell swoop:

  newest, oldest = Dir["C:/New"].map{|f| [f,File.mtime(f)] }.sort_by{|
i|i[1]}.map{|i| i[0]}.values_at(0,-1)

This is known as a "Swartzian Transform"

-- Mark.
Cf63da956b6ba955687a2f2f262928cb?d=identicon&s=25 Mmcolli00 Mom (mmcolli00)
on 2008-12-18 21:33
Thanks Mark.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2008-12-18 23:50
(Received via mailing list)
On 18.12.2008 20:52, Mark Thomas wrote:
> On Dec 18, 12:36 pm, Mmcolli00 Mom <mmc_coll...@yahoo.com> wrote:
>> If you have a directory full of files, how can you get the newest file
>> and oldest file from that directory?
>
> One way...
>
>   ages = Dir["C:/New"].map{|f| [f,File.mtime(f)] }.sort_by{|i|i[1]}

IMHO that should read

ages = Dir.entries("C:/New").map{|f|
[f,File.mtime(File.join("C:/New",f))] }.sort_by{|i|i[1]}

But:

> Or, if you want it in one fell swoop:
>
>   newest, oldest = Dir["C:/New"].map{|f| [f,File.mtime(f)] }.sort_by{|
> i|i[1]}.map{|i| i[0]}.values_at(0,-1)

We can do better, i.e. #map is superfluous

sorted = Dir.entries(dir).sort_by {|f| File.mtime(File.join(dir,f))}
puts sorted.first, sorted.last

Kind regards

  robert
4df097f56911b410a879c81c176b2d9c?d=identicon&s=25 Mike Cargal (Guest)
on 2008-12-19 01:38
(Received via mailing list)
Just a pet peeve.... but... Sorts are expensive and should be avoided
when possible.  Finding min and max values are prime examples.

So...

newest = Dir.entries(dir).max {|a,b| (File.mtime(File.join(dir,a)) <=>
File.mtime(File.join(dir,b)))}
Cf63da956b6ba955687a2f2f262928cb?d=identicon&s=25 Mmcolli00 Mom (mmcolli00)
on 2008-12-19 03:55
Thanks Everyone! Great advice!
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2008-12-19 09:24
(Received via mailing list)
2008/12/19 Mike Cargal <mike@cargal.net>:
> Just a pet peeve.... but... Sorts are expensive and should be avoided when
> possible.  Finding min and max values are prime examples.
>
> So...
>
> newest = Dir.entries(dir).max {|a,b| (File.mtime(File.join(dir,a)) <=>
> File.mtime(File.join(dir,b)))}

While we're nitpicking... :-)  In this case File.mtime is most likely
the most expensive operation as it does IO (or at least has to travel
into system call land). #max will invoke File.mtime multiple times for
the same file.

So, efficiency wise an explicit one pass solution is probably best:

max = Time.at 0
file = nil

Dir.open(dir) do |d|
  d.each do |f|
    mt = File.mtime(File.join(dir, f))
    if mt > max
      max = mt
      file = f
    end
  end
end

puts file

Btw, there is another nice short solution, which unfortunately also
suffers the multiple #mtime per File issue (you can easily see this by
placing "p f;" before the "File.mtime" in the block):

puts Dir.open(dir) {|d| d.max_by {|f| File.mtime(File.join(dir, f))}}

Kind regards

robert
This topic is locked and can not be replied to.