Show newest file in directory?

M

Mmcolli00 Mom

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
 
M

Mark Thomas

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.
 
R

Robert Klemme

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
 
M

Mike Cargal

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)))}


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
 
R

Robert Klemme

2008/12/19 Mike Cargal said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top