2010-10-09 30 views
5

je dois code suivant dans Ruby:Dans Ruby, comment lister/trier les fichiers avant les dossiers dans une liste de répertoires?

<% 
    files = Dir.glob('/**/*') 
    files.each do |file| 
    puts file 
    end 
%> 

Il produit (par exemple):

/dirA/file1.txt 
/dirA/file2.txt 
/dirB/file1.txt 
/file1.txt 
/file2.txt 
/subdirA/file1.txt 

Je veux à la sortie comme ceci:

/file1.txt 
/file2.txt 
/dirA/file1.txt 
/dirA/file2.txt 
/dirB/file1.txt 
/subdirA/file1.txt 

Fondamentalement, je J'aimerais avoir les fichiers affichés avant les répertoires. Y a-t-il une commande de tri que je peux utiliser?

Répondre

6

Je crois que cela devrait fonctionner pour vous:

files = Dir.glob('**/*') 
files = files.map { |file| [file.count("/"), file] } 
files = files.sort.map { |file| file[1] } 
files.each do |file| 
    puts file 
end 

changement "/" à ?/ si vous êtes sur Ruby 1.8.

Ou, comme un paquebot: :)

Dir.glob('**/*').map { |file| [file.count("/"), file] }.sort.map { |file| file[1] }.each { |file| puts file } 
+0

qui fonctionne !! MERCI! –

+2

'Enumerable # sort_by' rend la transformation Schwartzian plus facile à suivre, et' String # count' fonctionne à la fois sur 1.8 et 1.9: 'files = Dir.glob ('**/*'). Sort_by {| file | [fichier.count ("/"), fichier]} '. (Le tableau est toujours nécessaire pour rompre les liens entre les noms de fichiers avec le même nombre de barres obliques.) – bk1e

+0

Je ne comprends pas pourquoi 'sort_by' serait nécessaire; critère de tri de tableau devrait être correct, non? (comparez les premiers éléments, si c'est le même, passez au suivant.) Je ne veux pas mettre de comptage à l'intérieur du bloc de comparaison car ce serait inefficace (je ne pense pas que Ruby soit assez intelligent pour mémoriser tout seul). Je ne connaissais pas 'String # count'; Merci pour ça. L'utiliser serait certainement plus élégant. Je vais l'éditer. – Amadan

1
d,f = Dir.glob('*').partition{|d|test(?d,d)} 
d.sort.each{|x|puts x} 
f.sort.each{|y|puts y}