2011-11-02 59 views
9

我是Ruby新手(作爲Java開發人員)並試圖實現一種方法(哦,對不起,一個函數),它將遞歸檢索併產生子目錄中的所有文件。Ruby中的遞歸文件列表

我實現它:

def file_list_recurse(dir) 
    Dir.foreach(dir) do |f| 
    next if f == '.' or f == '..' 
    f = dir + '/' + f 
    if File.directory? f 
     file_list_recurse(File.absolute_path f) { |x| yield x } 
    else 
     file = File.new(f) 
     yield file 
    end 
    end 
end 

我的問題是:

  1. 不File.new真正打開一個文件?在Java新的文件(「xxx」)不......如果我需要產生一些結構,我可以查詢文件信息(ctime,大小等)從它將在Ruby中會是什麼?
  2. {| x | yield x}對我來說看起來有點奇怪,是否可以通過類似遞歸函數來產生收益,還是有一些方法可以避免它?
  3. 有沒有辦法避免檢查'。'和'..'在每次迭代?
  4. 有沒有更好的方法來實現這個?

感謝

PS: 我的方法的示例用法是這樣的:

curr_file = nil 

file_list_recurse('.') do |file| 
    curr_file = file if curr_file == nil or curr_file.ctime > file.ctime 
end 

puts curr_file.to_path + ' ' + curr_file.ctime.to_s 

(這將讓你從樹上最早的文件)

= =========

所以,感謝@buruza埃蒙我發現了偉大的Dir.glob函數,它爲我節省了幾行代碼。 此外,由於@Casper我發現了File.stat方法,這使我的功能運行比File.new

快兩倍到底我的代碼看起來像這樣:

i=0 
curr_file = nil 

Dir.glob('**/*', File::FNM_DOTMATCH) do |f| 
    file = File.stat(f) 
    next unless file.file? 
    i += 1 
    curr_file = [f, file] if curr_file == nil or curr_file[1].ctime > file.ctime 
end 

puts curr_file[0] + ' ' + curr_file[1].ctime.to_s 
puts "total files #{i}" 

=====

默認Dir.glob忽略文件名開頭的一個點(認爲* nix中被「隱藏」),所以要加第二個參數文件是非常重要:: FNM_DOTMATCH

回答

5

這件事情告訴我考慮接受一個答案,我希望它不會介意我回答我自己:

i=0 
curr_file = nil 

Dir.glob('**/*', File::FNM_DOTMATCH) do |f| 
    file = File.stat(f) 
    next unless file.file? 
    i += 1 
    curr_file = [f, file] if curr_file == nil or curr_file[1].ctime > file.ctime 
end 

puts curr_file[0] + ' ' + curr_file[1].ctime.to_s 
puts "total files #{i}" 
2

您可以使用內置的Find模塊的find方法。

11

這個怎麼樣?

puts Dir['**/*.*'] 
+0

這是偉大的!但它會產生一個String對象數組。我在尋找的是一個函數,它會產生一個類似於文件的結構,以便我可以根據它進行自己的計算。找到最大的文件,最早的ctime等。 –

+0

Dir ['。']不接受一個塊。但是Dir.glob呢!它回答我的問題,除了#1問題 –

5

根據文檔File.new打開文件。您可能需要使用File.stat,它將與文件相關的統計信息收集到可查詢對象中。但請注意,統計信息是在創建點收集的。當您調用類似ctime的查詢方法時,不是。

例子:

Dir['**/*'].select { |f| File.file?(f) }.map { |f| File.stat(f) } 
+1

File.stat具有諷刺意味的是不提供文件的名稱,所以我不能用它作爲數據對象從我的方法返回。 另外,我有一個200,000個文件的樹。 運行您的示例結果在ruby進程增長超過60 Mb,同時運行我的方法(即使使用File.new)永遠不會讓紅寶石超過6 Mb。 (我正在測試-n 0,1「ps ax -o comm,rss | grep ruby​​ >>/tmp/q」)。 但你樣品代碼的行確實看起來很酷;-) –