আমি রুবি ব্যবহার করে একটি ফোল্ডার থেকে সমস্ত ফাইলের নাম পেতে চাই।
আমি রুবি ব্যবহার করে একটি ফোল্ডার থেকে সমস্ত ফাইলের নাম পেতে চাই।
উত্তর:
আপনার শর্টকাট বিকল্পও রয়েছে
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], দির ব্যবহার করুন [] :
# 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 }
এখন, ডি.আরন্ট্রিগুলি লুকানো ফাইলগুলি ফিরিয়ে দেবে, এবং আপনার ওয়াইল্ডকার্ড অ্যাসেরিক্সের প্রয়োজন হবে না (আপনি কেবল ডিরেক্টরি নামের সাথে ভেরিয়েবলটি পাস করতে পারেন) তবে এটি সরাসরি বেস নামটি ফিরিয়ে দেবে, সুতরাং ফাইল.এক্সএক্সএক্সএক্স ফাংশনগুলি কাজ করবে না ।
# 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
এপিআই অনুসারে:
ফাইললিস্টগুলি অলস। ফাইল তালিকাতে অন্তর্ভুক্ত করার জন্য সম্ভাব্য ফাইলগুলির জন্য গ্লোব প্যাটার্নগুলির একটি তালিকা দেওয়া হলে ফাইলগুলি অনুসন্ধান করার জন্য ফাইলের কাঠামোগুলি অনুসন্ধান করার পরিবর্তে, একটি ফাইললিস্ট পরে ব্যবহারের জন্য প্যাটার্ন ধারণ করে।
আপনি যদি সিমলিংক সহ ফাইলের নামের একটি অ্যারে পেতে চান তবে ব্যবহার করুন
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')
।
*.*
এই থ্রেডের পরামর্শ ছাড়াও, আমি উল্লেখ করতে চাইছিলাম যে আপনার যদি Dir.glob এর সাথে ডট ফাইলও (.gitignore, ইত্যাদি) ফেরত দরকার হয় তবে আপনাকে একটি পতাকাও অন্তর্ভুক্ত করতে হবে:
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
কোনও ফাইল ডিরেক্টরি ছিল কিনা তা নির্ধারণ করার জন্য ফাইলটির পরম পাথটি পুনর্নির্মাণের প্রয়োজনের কারণে এই ক্ষেত্রে কিছুটা বেশি সময় নিয়ে শেষ হয়েছিল, তবে তা ছাড়া এটি পুনরাবৃত্তির ক্ষেত্রে অন্যান্য বিকল্পগুলির তুলনায় ধারাবাহিকভাবে আরও বেশি সময় নিচ্ছিল। এটি সমস্ত ওএসএক্সে রুবি 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
ডিরেক্টরি এবং সমস্ত উপ-ডিরেক্টরি থেকে ফাইলের আপেক্ষিক পাথ ফেরত দেয়
আইআরবি প্রসঙ্গে আপনি বর্তমান ডিরেক্টরিতে ফাইলগুলি পেতে নিম্নলিখিতটি ব্যবহার করতে পারেন:
file_names = `ls`.split("\n")
আপনি অন্যান্য ডিরেক্টরিতেও এই কাজটি করতে পারেন:
file_names = `ls ~/Documents`.split("\n")