2009-11-18 4 views

ответ

401

У вас также есть возможность кратчайшего

Dir["/path/to/search/*"] 

и если вы хотите, чтобы найти все файлы Ruby, в любой папке или подпапка:

Dir["/path/to/search/**/*.rb"] 
+5

Или вы можете сделать то же самое с Dir :: glob() –

+1

Спасибо большое, я использую Dir [] прямо сейчас. :) –

+2

Кроме того, используйте './...' вместо '~ /' –

129
Dir.entries(folder) 

пример:

Dir.entries(".") 

Источник: http://ruby-doc.org/core/classes/Dir.html#method-c-entries

+13

Похоже, он использует SO документировать ответы на вопросы, он просто спросил. Похоже, это напоминание. Не могу видеть много плохого, что - в конце концов, даже если это один немного неполный ('Dir # мог бы, возможно, были упомянуты glob', например) нет ничего, чтобы предотвратить кого-то разместить действительно хороший ответ. «Конечно, я по большей части„стакан наполовину полный“вид парня ... –

+1

@ Mike: В великой схеме вещей, это, вероятно, не имеет большого значения. И, как вы говорите, если вопросы и ответы были хорошими, это может быть плюс для всего сайта. Но здесь и вопрос, и ответ настолько минимальны, что это не кажется особенно полезным. – Telemachus

+13

@Telemachus Я использую 'Dir' редко, и каждый раз, когда мне это нужно, я должен читать документацию. Я разместил свой вопрос и ответ, чтобы найти его позже, и, возможно, даже помогу кому-то с тем же вопросом. Я думаю, что слышал в SO подкаст, что нет ничего плохого в таком поведении. Если у вас есть лучший ответ, отправьте его. Я опубликовал то, что знаю, я не ниндзя Ruby. Я регулярно принимаю ответы с большинством голосов. –

73

Следующие фрагменты точно показывает имена файлов внутри каталога, пропустив подкаталоги и ".", ".." пунктирные папки:

Dir.entries("your/folder").select {|f| !File.directory? f} 
+16

Может также делать '... select {| f | File.file? f} 'для более четкого значения и более короткого синтаксиса. – Automatico

+0

Я вижу, что Dir.entries не дает полный путь в обратном имени файла, поэтому это решение не сработало для меня. –

+4

@ Cort3z, не работает для меня. – squixy

27

Чтобы получить все файлы (строго только для файлов) рекурсивно:

Dir.glob('path/**/*').select{ |e| File.file? e } 

Или что-нибудь, что это не является каталогом (File.file? отвергнет непостоянные файлы):

Dir.glob('path/**/*').reject{ |e| File.directory? e } 

Альтернативное решение

Использование Find#find над рисунком на основе метода поиска как Dir.glob на самом деле лучше. См. this answer to "One-liner to Recursively List Directories in Ruby?".

8

Лично я нашел это самое полезное для зацикливания над файлами в папке, прогнозный безопасности:

Dir['/etc/path/*'].each do |file_name| 
    next if File.directory? file_name 
end 
6

Это решение для поиска файлов в каталоге:

files = Dir["/work/myfolder/**/*.txt"] 

files.each do |file_name| 
    if !File.directory? file_name 
    puts file_name 
    File.open(file_name) do |file| 
     file.each_line do |line| 
     if line =~ /banco1/ 
      puts "Found: #{line}" 
     end 
     end 
    end 
    end 
end 
3

While получение всех имен файлов в каталоге, этот фрагмент может использоваться для отклонения обоих каталогов [., ..] и скрытых файлов, начинающихся с .

files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')} 
+0

' Dir.entries' возвращает имена локальных файлов, а не абсолютные пути к файлам. С другой стороны, 'File.directory? 'Ожидает абсолютный путь к файлу. Этот код работает не так, как ожидалось. – Nathan

+0

Странно, что код не работает в вашем случае. Поскольку это код, который я использовал в реальном приложении, которое работает отлично. Я перепроверяю свой код и публикую здесь, если в моем исходном рабочем коде ничего не осталось :) – Lahiru

+1

@Nathan См. Мой ответ для объяснения – nus

0
def get_path_content(dir) 
    queue = Queue.new 
    result = [] 
    queue << dir 
    until queue.empty? 
    current = queue.pop 
    Dir.entries(current).each { |file| 
     full_name = File.join(current, file) 
     if not (File.directory? full_name) 
     result << full_name 
     elsif file != '.' and file != '..' 
      queue << full_name 
     end 
    } 
    end 
    result 
end 

возвращает относительные пути файла из директории и поддиректорий

7

Это работает для меня:

Если вы не хотите, скрытые файлы [1], используйте Dir []:

# With a relative path, Dir[] will return relative paths 
# as `[ './myfile', ... ]` 
# 
Dir[ './*' ].select{ |f| File.file? f } 

# Want just the filename? 
# as: [ 'myfile', ... ] 
# 
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.basename f } 

# Turn them into absolute paths? 
# [ '/path/to/myfile', ... ] 
# 
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.absolute_path f } 

# With an absolute path, Dir[] will return absolute paths: 
# as: [ '/home/../home/test/myfile', ... ] 
# 
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f } 

# Need the paths to be canonical? 
# as: [ '/home/test/myfile', ... ] 
# 
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f }.map{ |f| File.expand_path f } 

Теперь Dir.entries будет возвращать скрытые файлы и вам не нужен подстановочная астра ix (вы можете просто передать переменную с именем каталога), но она вернет базовое имя напрямую, поэтому функции File.xxx не будут работать.

# In the current working dir: 
# 
Dir.entries('.').select{ |f| File.file? f } 

# In another directory, relative or otherwise, you need to transform the path 
# so it is either absolute, or relative to the current working dir to call File.xxx functions: 
# 
home = "/home/test" 
Dir.entries(home).select{ |f| File.file? File.join(home, f) } 

[1] .dotfile на Unix, я не знаю о Windows,

0

Если вы хотите получить массив имен файлов включая Symlinks, используйте

Dir.new('/path/to/dir').entries.reject { |f| File.directory? f } 

или даже

Dir.new('/path/to/dir').reject { |f| File.directory? f } 

и если вы хотите пойти без симлинками используйте

Dir.new('/path/to/dir').select { |f| File.file? f } 

Как показано в других ответах, используйте Dir.glob('/path/to/dir/**/*') вместо Dir.new('/path/to/dir'), если вы хотите, чтобы получить все файлы рекурсивно.

+0

Или просто используйте '*. *' –

1

Это то, что работает для меня:

Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) } 

Dir.entries возвращает массив строк. Затем мы должны предоставить полный путь файла к File.file?, если dir не соответствует нашей текущей рабочей директории. Вот почему это File.join().

0

Вы также можете использовать Rake::FileList (если у вас есть rake зависимость):

FileList.new('lib/*') do |file| 
    p file 
end 

Согласно API:

списки файлов ленивы. При задании списка шаблонов glob для возможных файлов , которые должны быть включены в список файлов, вместо поиска в файле структур для поиска файлов FileList хранит шаблон для последних .

https://docs.ruby-lang.org/en/2.1.0/Rake/FileList.html