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
On Dec 18, 12:36 pm, Mmcolli00 Mom [email protected] 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.
On 18.12.2008 20:52, Mark T. wrote:
On Dec 18, 12:36 pm, Mmcolli00 Mom [email protected] 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
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)))}
Thanks Everyone! Great advice!
2008/12/19 Mike C. [email protected]:
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