Получить имена всех файлов из папки с Ruby - PullRequest
317 голосов
/ 18 ноября 2009

Я хочу получить все имена файлов из папки, используя Ruby.

Ответы [ 16 ]

1 голос
/ 30 октября 2018

В дополнение к предложениям в этой теме я хотел бы упомянуть, что если вам нужно также возвращать точечные файлы (.gitignore и т. Д.), То в Dir.glob вам нужно будет включить флаг следующим образом: Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH) По умолчанию Dir.entries включает точечные файлы, а также текущие родительские каталоги.

Для всех, кому было интересно, мне было любопытно, как здесь ответы сравниваются друг с другом во время выполнения, вот результаты против глубоко вложенной иерархии. Первые три результата не являются рекурсивными:

       user     system      total        real
Dir[*]: (34900 files stepped over 100 iterations)
  0.110729   0.139060   0.249789 (  0.249961)
Dir.glob(*): (34900 files stepped over 100 iterations)
  0.112104   0.142498   0.254602 (  0.254902)
Dir.entries(): (35600 files stepped over 100 iterations)
  0.142441   0.149306   0.291747 (  0.291998)
Dir[**/*]: (2211600 files stepped over 100 iterations)
  9.399860  15.802976  25.202836 ( 25.250166)
Dir.glob(**/*): (2211600 files stepped over 100 iterations)
  9.335318  15.657782  24.993100 ( 25.006243)
Dir.entries() recursive walk: (2705500 files stepped over 100 iterations)
 14.653018  18.602017  33.255035 ( 33.268056)
Dir.glob(**/*, File::FNM_DOTMATCH): (2705500 files stepped over 100 iterations)
 12.178823  19.577409  31.756232 ( 31.767093)

Они были сгенерированы с помощью следующего сценария бенчмаркинга:

require 'benchmark'
base_dir = "/path/to/dir/"
n = 100
Benchmark.bm do |x|
  x.report("Dir[*]:") do
    i = 0
    n.times do
      i = i + Dir["#{base_dir}*"].select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.glob(*):") do
    i = 0
    n.times do
      i = i + Dir.glob("#{base_dir}/*").select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.entries():") do
    i = 0
    n.times do
      i = i + Dir.entries(base_dir).select {|f| !File.directory? File.join(base_dir, f)}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir[**/*]:") do
    i = 0
    n.times do
      i = i + Dir["#{base_dir}**/*"].select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.glob(**/*):") do
    i = 0
    n.times do
      i = i + Dir.glob("#{base_dir}**/*").select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.entries() recursive walk:") do
    i = 0
    n.times do
      def walk_dir(dir, result)
        Dir.entries(dir).each do |file|
          next if file == ".." || file == "."

          path = File.join(dir, file)
          if Dir.exist?(path)
            walk_dir(path, result)
          else
            result << file
          end
        end
      end
      result = Array.new
      walk_dir(base_dir, result)
      i = i + result.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.glob(**/*, File::FNM_DOTMATCH):") do
    i = 0
    n.times do
      i = i + Dir.glob("#{base_dir}**/*", File::FNM_DOTMATCH).select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
end

Различия в количестве файлов обусловлены Dir.entries, включая скрытые файлы по умолчанию. Dir.entries в этом случае занял немного больше времени из-за необходимости перестроить абсолютный путь к файлу, чтобы определить, был ли файл каталогом, но даже без этого он все еще занимал значительно больше времени, чем другие параметры в рекурсивном случае , Это все с использованием ruby ​​2.5.1 на OSX.

1 голос
/ 24 октября 2017

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

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

Согласно API:

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

https://docs.ruby -lang.org / ен / 2.1.0 / Грабли / FileList.html

1 голос
/ 06 января 2017
Dir.new('/home/user/foldername').each { |file| puts file }
1 голос
/ 03 января 2017

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

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 голосов
/ 03 марта 2019

В контексте IRB вы можете использовать следующее для получения файлов в текущем каталоге:

file_names = `ls`.split("\n")

Вы можете сделать эту работу и в других каталогах:

file_names = `ls ~/Documents`.split("\n")
0 голосов
/ 21 июня 2016
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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...