Obtén nombres de todos los archivos de una carpeta con Ruby
file folder (15)
Además de las sugerencias en este hilo, quiero mencionar que si también necesita devolver archivos de puntos (.gitignore, etc.), con Dir.glob deberá incluir una Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH)
como tal: Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH)
De forma predeterminada, Dir.entries incluye archivos de puntos, así como directorios principales actuales.
Para cualquier persona interesada, tenía curiosidad por cómo las respuestas aquí se comparaban entre sí en el tiempo de ejecución, aquí estaban los resultados contra una jerarquía profundamente anidada. Los primeros tres resultados son no recursivos:
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)
Estos se generaron con el siguiente script de benchmarking:
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
Las diferencias en los recuentos de archivos se deben a Dir.entries
incluidos los archivos ocultos de forma predeterminada. Dir.entries
terminó tomando un poco más de tiempo en este caso debido a la necesidad de reconstruir la ruta absoluta del archivo para determinar si un archivo era un directorio, pero aún sin eso, seguía tomando consistentemente más tiempo que las otras opciones en el caso recursivo . Todo esto estaba usando ruby 2.5.1 en OSX.
Quiero obtener todos los nombres de archivos de una carpeta usando Ruby.
Al obtener todos los nombres de archivo en un directorio, este fragmento de código se puede usar para rechazar ambos directorios [ .
, ..
] y archivos ocultos que comienzan con a .
files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?(''.'')}
En Ruby 2.5 ahora puedes usar Dir.children
. Obtiene los nombres de archivo como una matriz a excepción de "." y ".."
Ejemplo:
Dir.children("testdir") #=> ["config.h", "main.rb"]
Esta es una solución para encontrar archivos en un directorio:
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
Esto es lo que funciona para mí:
Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }
Dir.entries
devuelve una matriz de cadenas. Entonces, tenemos que proporcionar una ruta completa del archivo a File.file?
, a menos que dir
sea igual a nuestro directorio de trabajo actual. Es por eso que este File.join()
.
Esto funciona para mí:
Si no quieres archivos ocultos [1], usa 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 }
Ahora, Dir.entries devolverá los archivos ocultos, y no necesita el asterisco (puede pasar la variable con el nombre del directorio), pero devolverá el nombre base directamente, por lo que las funciones File.xxx no funcionarán .
# 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
en unix, no sé acerca de Windows
Los siguientes fragmentos de código muestran exactamente el nombre de los archivos dentro de un directorio, omitiendo los subdirectorios y "."
, ".."
carpetas de puntos:
Dir.entries("your/folder").select {|f| !File.directory? f}
Para obtener todos los archivos (solo archivos estrictamente) recursivamente:
Dir.glob(''path/**/*'').select{ |e| File.file? e }
O cualquier cosa que no sea un directorio ( File.file?
Rechazaría archivos no regulares):
Dir.glob(''path/**/*'').reject{ |e| File.directory? e }
Solución alternativa
Usar Find#find
sobre un método de búsqueda basado en patrones como Dir.glob
es realmente mejor. Consulte esta respuesta en "¿Una línea para enumerar de forma recursiva los directorios en Ruby?" .
Personalmente, encontré que esto es lo más útil para hacer bucles sobre archivos en una carpeta, mirando hacia el futuro:
Dir[''/etc/path/*''].each do |file_name|
next if File.directory? file_name
end
Si desea obtener una variedad de nombres de archivos que incluyan enlaces simbólicos , use
Dir.new(''/path/to/dir'').entries.reject { |f| File.directory? f }
o incluso
Dir.new(''/path/to/dir'').reject { |f| File.directory? f }
y si quieres ir sin enlaces simbólicos , utiliza
Dir.new(''/path/to/dir'').select { |f| File.file? f }
Como se muestra en otras respuestas, use Dir.glob(''/path/to/dir/**/*'')
lugar de Dir.new(''/path/to/dir'')
si desea obtener todos los archivos de forma recursiva.
También puede usar Rake::FileList
(siempre que tenga dependencia de rake
):
FileList.new(''lib/*'') do |file|
p file
end
Según la API:
Las listas de archivos son perezosas. Cuando se le proporciona una lista de patrones globales para los posibles archivos que se incluirán en la lista de archivos, en lugar de buscar en las estructuras de archivos para encontrar los archivos, una Lista de archivos guarda el patrón para su uso posterior.
También tienes la opción de acceso directo de
Dir["/path/to/search/*"]
y si desea buscar todos los archivos de Ruby en cualquier carpeta o subcarpeta:
Dir["/path/to/search/**/*.rb"]
Dir.entries(folder)
ejemplo:
Dir.entries(".")
Fuente: http://ruby-doc.org/core/classes/Dir.html#method-c-entries
Dir.new(''/home/user/foldername'').each { |file| puts file }
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
devuelve las rutas relativas del archivo desde el directorio y todos los subdirectorios