Tüm dosya adlarını Ruby kullanarak bir klasörden almak istiyorum.
Tüm dosya adlarını Ruby kullanarak bir klasörden almak istiyorum.
Yanıtlar:
Ayrıca kısayol seçeneğiniz de var
Dir["/path/to/search/*"]
ve tüm Ruby dosyalarını herhangi bir klasör veya alt klasörde bulmak istiyorsanız:
Dir["/path/to/search/**/*.rb"]
./...
yerine kullanın~/
./
geçerli dizin anlamına gelir, oysa /
kök bağlama noktası ve ~/
kullanıcının ana dizini. Tüm projeyi başka bir yere taşırsanız, birincisi işe yarar, ancak diğer ikisi muhtemelen işe yaramaz.
Dir.entries(folder)
misal:
Dir.entries(".")
Kaynak: http://ruby-doc.org/core/classes/Dir.html#method-c-entries
Dir#glob
örneğin, belki de bahsedilebilirdi), başka birinin Gerçekten İyi Bir Yanıt göndermesini engelleyecek hiçbir şey yok. 'course, ben çoğunlukla "cam yarı dolu" bir adamım ...
Dir
Nadiren kullanıyorum ve her ihtiyaç duyduğumda belgeleri okumak zorundayım. Sorumu daha sonra bulabilmem için buraya gönderdim ve yanıtladım ve hatta aynı soruyu bilen birine yardım edebilirim. Sanırım SO podcast'de böyle bir davranışta yanlış bir şey olmadığını duydum. Daha iyi bir cevabınız varsa, lütfen gönderin. Bildiklerimi yayınladım, Ruby Ruby değilim. En çok oyu alan cevapları düzenli olarak kabul ediyorum.
Dir[]
veya Dir.glob
bu değişkenten daha iyi bir seçenek olabilir . Ne zaman path = '/tmp'
, karşılaştırma: Dir.glob("#{path}/*")
vs Dir.entries(path)
. Dönüş değerleri biraz farklıdır (".", ".."), ancak ikincisine hızlı bir bakışla bakılması daha kolaydır.
Aşağıdaki parçacıkları tam bir dizin içindeki dosya, atlama alt dizinleri ve adını gösterir "."
, ".."
noktalı klasörler:
Dir.entries("your/folder").select {|f| !File.directory? f}
...select {|f| File.file? f}
Daha net anlam ve daha kısa sözdizimi için de yapabilir .
Dir.entries("your/folder").select {|f| File.file? f}
!File.directory?
çalışıyor ama File.file?
çalışmıyor.
.reject {|f| File.directory? f}
daha temiz görünüyor .select{|f| !File.directory? f}
. Oh, ve şimdi ilk yorumu görüyorum ... ayrıca iyi.
Tüm dosyaları (yalnızca dosyalar) yinelemeli olarak almak için:
Dir.glob('path/**/*').select{ |e| File.file? e }
Veya dizin File.file?
olmayan herhangi bir şey ( normal olmayan dosyaları reddeder):
Dir.glob('path/**/*').reject{ |e| File.directory? e }
Kullanımı Find#find
gibi bir desen tabanlı arama yöntemi üzerinde Dir.glob
aslında iyidir. Bkz için bu cevabı "Ruby yinelemeli Liste Dizinler Tek astar?" .
Bu benim için çalışıyor:
Gizli dosya istemiyorsanız [1], Dir [] kullanın :
# 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 }
Şimdi, Dir.entries gizli dosyaları döndürür ve joker karakter asterixine ihtiyacınız yoktur (değişkeni dizin adıyla geçirebilirsiniz), ancak doğrudan temel adı döndürür, böylece File.xxx işlevleri çalışmaz .
# 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'te Windows hakkında bir fikrim yok
Ruby 2.5'te artık kullanabilirsiniz Dir.children
. Dosya adlarını "." Dışında bir dizi olarak alır. ve ".."
Misal:
Dir.children("testdir") #=> ["config.h", "main.rb"]
Şahsen, bunu bir klasördeki dosyalar üzerinde ileriye dönük güvenlik için en kullanışlı buldum:
Dir['/etc/path/*'].each do |file_name|
next if File.directory? file_name
end
Bu, bir dizindeki dosyaları bulmak için bir çözümdür:
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
Bir dizindeki tüm dosya adlarını alırken, bu pasajı, hem dizinleri [reddetmek için kullanılabilir .
, ..
a ile başlar] ve gizli dosyaları.
files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}
Dir.entries
mutlak dosya yollarını değil, yerel dosya adlarını döndürür. Öte yandan, File.directory?
mutlak bir dosya yolu bekler. Bu kod beklendiği gibi çalışmıyor.
bu kod yalnızca uzantılarıyla birlikte dosya adlarını döndürür (genel yol olmadan)
Dir.children("/path/to/search/")
İşte benim işime yarayan bu:
Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }
Dir.entries
bir dizgi dizisi döndürür. Ardından, geçerli çalışma dizinimize eşit File.file?
olmadığı sürece dosyanın tam yolunu sağlamalıyız dir
. Bu yüzden bu File.join()
.
Ayrıca kullanmak isteyebilirsiniz Rake::FileList
( rake
bağımlılığınız varsa):
FileList.new('lib/*') do |file|
p file
end
API'ya göre:
Dosya Listeleri tembeldir. Dosyaları bulmak için dosya yapılarını aramak yerine, dosya listesine dahil edilecek olası dosyalar için bir glob kalıpları listesi verildiğinde, bir FileList, ikinci kullanım için kalıbı tutar.
Simge bağlantıları da dahil olmak üzere bir dizi dosya adı almak istiyorsanız şunu kullanın:
Dir.new('/path/to/dir').entries.reject { |f| File.directory? f }
ya da
Dir.new('/path/to/dir').reject { |f| File.directory? f }
ve sembolik bağlar olmadan gitmek istiyorsanız ,
Dir.new('/path/to/dir').select { |f| File.file? f }
Diğer yanıtlarda gösterildiği gibi, tüm dosyaları yinelemeli olarak almak istiyorsanız Dir.glob('/path/to/dir/**/*')
yerine kullanın Dir.new('/path/to/dir')
.
*.*
Bu konudaki önerilere ek olarak, nokta dosyalarını da (.gitignore vb.) Döndürmeniz gerekiyorsa, Dir.glob ile bir bayrak eklemeniz gerektiğini belirtmek Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH)
istedim :
Varsayılan olarak, Dir.entries nokta dosyaları ve geçerli bir üst dizinleri içerir.
İlgilenen herkes için, burada cevapların yürütme zamanında nasıl karşılaştırıldığını merak ettim, işte derin iç içe hiyerarşiye karşı sonuçlar oldu. İlk üç sonuç özyinelemesizdir:
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)
Bunlar aşağıdaki karşılaştırma komut dosyasıyla oluşturuldu:
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
Dosya sayımlarındaki farklar, Dir.entries
varsayılan olarak gizli dosyaların dahil edilmesinden kaynaklanmaktadır . Dir.entries
bir dosyanın bir dizin olup olmadığını belirlemek için dosyanın mutlak yolunu yeniden oluşturmaya ihtiyaç duyması nedeniyle bu durumda biraz daha uzun sürdü, ancak bu olmadan bile özyinelemeli durumda diğer seçeneklerden sürekli olarak daha uzun sürüyordu. Bunların hepsi OSX'te ruby 2.5.1 kullanıyordu.
Basit bir yol olabilir:
dir = './' # desired directory
files = Dir.glob(File.join(dir, '**', '*')).select{|file| File.file?(file)}
files.each do |f|
puts f
end
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
dizinden ve tüm alt dizinlerden dosyanın göreli yollarını döndürür
IRB bağlamında, geçerli dizindeki dosyaları almak için aşağıdakileri kullanabilirsiniz:
file_names = `ls`.split("\n")
Bu işlemi diğer dizinlerde de yapabilirsiniz:
file_names = `ls ~/Documents`.split("\n")