मैं रूबी का उपयोग करके एक फ़ोल्डर से सभी फ़ाइल नाम प्राप्त करना चाहता हूं।
मैं रूबी का उपयोग करके एक फ़ोल्डर से सभी फ़ाइल नाम प्राप्त करना चाहता हूं।
जवाबों:
आपके पास शॉर्टकट का विकल्प भी है
Dir["/path/to/search/*"]
और यदि आप किसी भी फ़ोल्डर या उप-फ़ोल्डर में सभी रूबी फाइलें ढूंढना चाहते हैं:
Dir["/path/to/search/**/*.rb"]
./...
करने के बजाय~/
./
अर्थ है वर्तमान निर्देशिका, जबकि /
रूट माउंट बिंदु है, और ~/
उपयोगकर्ता की होम निर्देशिका है। यदि आप पूरी परियोजना को कहीं और स्थानांतरित करते हैं, तो पहला काम करेगा, लेकिन अन्य दो शायद नहीं करेंगे।
Dir.entries(folder)
उदाहरण:
Dir.entries(".")
स्रोत: http://ruby-doc.org/core/classes/Dir.html#method-c-entries
Dir#glob
उदाहरण के लिए, शायद उदाहरण के लिए उल्लेख किया गया है), किसी और को वास्तव में अच्छा जवाब पोस्ट करने से रोकने के लिए कुछ भी नहीं है। 'बेशक, मैं ज्यादातर एक "ग्लास आधा भरा हुआ" एक आदमी हूँ ...
Dir
शायद ही कभी उपयोग करता हूं, और हर बार जब मुझे इसकी आवश्यकता होती है तो मुझे दस्तावेज़ीकरण पढ़ना पड़ता है। मैंने अपना प्रश्न और उत्तर यहाँ पोस्ट किया है ताकि मैं इसे बाद में पा सकूँ, और शायद उसी प्रश्न के साथ किसी की मदद भी कर सकूँ। मुझे लगता है कि मैंने एसओ पॉडकास्ट में सुना है कि इस तरह के व्यवहार में कुछ भी गलत नहीं है। यदि आपके पास बेहतर उत्तर है, तो कृपया इसे पोस्ट करें। मैंने जो जाना है उसे पोस्ट किया है, मैं रूबी निंजा नहीं हूं। मैं नियमित रूप से सबसे अधिक वोटों के साथ उत्तर स्वीकार करता हूं।
Dir[]
या Dir.glob
जब तर्क एक चर है। जब path = '/tmp'
, तुलना करें: Dir.glob("#{path}/*")
बनाम Dir.entries(path)
। रिटर्न मान थोड़े अलग हैं ("।", ".."), लेकिन बाद वाले को त्वरित नज़र में घिसना आसान है।
निम्नलिखित स्निपेट बिल्कुल एक निर्देशिका के अंदर फाइलों का नाम दिखाता है, उपनिर्देशिकाओं को छोड़ देता है और "."
, ".."
बिंदीदार फ़ोल्डर:
Dir.entries("your/folder").select {|f| !File.directory? f}
...select {|f| File.file? f}
स्पष्ट अर्थ और छोटे वाक्यविन्यास के लिए भी कर सकते हैं ।
Dir.entries("your/folder").select {|f| File.file? f}
!File.directory?
काम कर रहा है लेकिन File.file?
नहीं।
.reject {|f| File.directory? f}
से साफ लगता है .select{|f| !File.directory? f}
। ओह, और अब मैं पहली टिप्पणी देखता हूं ... अच्छा भी।
सभी फ़ाइलें (केवल सख्ती से फ़ाइलें) प्राप्त करने के लिए:
Dir.glob('path/**/*').select{ |e| File.file? e }
या कुछ भी जो एक निर्देशिका नहीं है ( File.file?
गैर-नियमित फ़ाइलों को अस्वीकार कर देगा):
Dir.glob('path/**/*').reject{ |e| File.directory? e }
Find#find
पैटर्न-आधारित लुकअप विधि का उपयोग करना Dir.glob
वास्तव में बेहतर है। देखें करने के लिए इस सवाल का जवाब "रूबी में रिकर्सिवली सूची निर्देशिकाएँ करने के लिए एक-लाइनर?" ।
यह मेरे लिए काम करता है:
यदि आप छिपी हुई फ़ाइलें नहीं चाहते हैं [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 छुपी हुई फ़ाइलों को वापस कर देगा, और आपको वाइल्डकार्ड asterix की आवश्यकता नहीं है (आप केवल निर्देशिका नाम के साथ चर को पास कर सकते हैं), लेकिन यह सीधे आधार को लौटा देगा, इसलिए 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
यूनिक्स पर, मैं विंडोज के बारे में नहीं जानता
रूबी 2.5 में अब आप उपयोग कर सकते हैं Dir.children
। इसे "के अलावा एक सरणी के रूप में फ़ाइल नाम मिलता है।" तथा ".."
उदाहरण:
Dir.children("testdir") #=> ["config.h", "main.rb"]
व्यक्तिगत रूप से, मैंने इसे एक फ़ोल्डर में फ़ाइलों पर लूपिंग के लिए सबसे उपयोगी पाया, आगे की ओर देख सुरक्षा:
Dir['/etc/path/*'].each do |file_name|
next if File.directory? file_name
end
यह एक निर्देशिका में फ़ाइलों को खोजने के लिए एक समाधान है:
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
एक निर्देशिका में सभी फ़ाइल नाम प्राप्त करते समय, इस स्निपेट का उपयोग दोनों निर्देशिका [ .
, ..
] और छिपी हुई फाइलों को अस्वीकार करने के लिए किया जा सकता है , जो एक के साथ शुरू होती हैं.
files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}
Dir.entries
स्थानीय फ़ाइल नाम देता है, न कि पूर्ण फ़ाइल पथ। दूसरी ओर, File.directory?
एक पूर्ण फ़ाइल पथ की अपेक्षा करता है। यह कोड अपेक्षा के अनुरूप काम नहीं करता है।
यह कोड केवल उनके एक्सटेंशन (वैश्विक पथ के बिना) के साथ फ़ाइल नाम देता है
Dir.children("/path/to/search/")
यह मेरे लिए काम करता है:
Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }
Dir.entries
स्ट्रिंग्स की एक सरणी देता है। फिर, हमें फ़ाइल का पूरा पथ प्रदान करना होगा File.file?
, जब तक dir
कि हमारी वर्तमान कार्यशील निर्देशिका के बराबर न हो । इसलिए ऐसा है File.join()
।
आप भी उपयोग करना चाहते हैं Rake::FileList
(बशर्ते आपके पास rake
निर्भरता हो):
FileList.new('lib/*') do |file|
p file
end
एपीआई के अनुसार:
FileLists आलसी हैं। जब फ़ाइल को सूची में शामिल करने के लिए संभावित फ़ाइलों के लिए ग्लोब पैटर्न की एक सूची दी जाती है, तो फ़ाइलों को खोजने के लिए फ़ाइल संरचनाओं को खोजने के बजाय, एक फाइललिस्ट बाद के उपयोग के लिए पैटर्न रखता है।
यदि आप सिमिलिंक , उपयोग सहित फ़ाइल नाम का एक सरणी प्राप्त करना चाहते हैं
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')
यदि आप सभी फ़ाइलों को पुन: प्राप्त करना चाहते हैं , तो इसका उपयोग करें ।
*.*
इस सूत्र में सुझावों के अलावा, मैं यह उल्लेख करना चाहता था कि अगर आपको डॉट फाइलें (.itignore, आदि) को वापस करने की आवश्यकता है, तो 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
फ़ाइल के पूर्ण पथ को फिर से बनाने के लिए यह निर्धारित करने की आवश्यकता के कारण इस मामले में थोड़ा अधिक समय लगना समाप्त हो जाता है कि क्या कोई फ़ाइल एक निर्देशिका थी, लेकिन इसके बावजूद कि यह अभी भी पुनरावर्ती मामले में अन्य विकल्पों की तुलना में लगातार अधिक समय ले रही थी। यह सब OSX पर रूबी 2.5.1 का उपयोग कर रहा था।
एक सरल तरीका हो सकता है:
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
निर्देशिका और सभी उपनिर्देशिकाओं से फ़ाइल के सापेक्ष पथ लौटाता है
IRB संदर्भ में, आप वर्तमान निर्देशिका में फ़ाइलों को प्राप्त करने के लिए निम्नलिखित का उपयोग कर सकते हैं:
file_names = `ls`.split("\n")
आप अन्य निर्देशिकाओं पर भी यह काम कर सकते हैं:
file_names = `ls ~/Documents`.split("\n")