एक निर्देशिका में हर फ़ाइल के माध्यम से Iterate


274

मैं माणिक में एक लूप कैसे लिखूं ताकि मैं प्रत्येक फ़ाइल पर कोड के ब्लॉक को निष्पादित कर सकूं?

मैं माणिक के लिए नया हूं, और मैंने निष्कर्ष निकाला है कि ऐसा करने का तरीका प्रत्येक लूप है।
जिस निर्देशिका को मैं लूप करना चाहता हूं, उसकी तुलना में रूबी फ़ाइल को एक अलग निर्देशिका से निष्पादित किया जाएगा।

मैंने कोशिश की है Dir.foreachऔर मैं इसे काम नहीं कर सका।


2
क्या आप बता सकते हैं कि जब आपने इसे काम करने की कोशिश की थी तब क्या हुआ था? आपने कौन सा सटीक कोड आज़माया (या यदि वह लंबे समय से संबंधित है)? आपको क्या त्रुटि संदेश मिले? Dir.foreachएक निर्देशिका की सामग्री पर पुनरावृति करने के लिए काम करता है, इसलिए कुछ और बहुत कुछ हो रहा है।
टेलीमैचस

3
यदि आप केवल अपनी निर्देशिका के भीतर फ़ाइलें चाहते हैं, तो फ़ाइलों के लिए परीक्षण करना न भूलें जब निर्देशिका सामग्री पर पुनरावृत्ति होती है: do_something_with(entry) if File.file?(entry)
ग्लेन जैकमैन

3
'img/*.{jpg,png,gif,jpeg}'एकाधिक एक्सटेंशन को हथियाने के लिए उपयोग करें ।
बेंजामिन क्राउज़ियर 16

@ChrisPeters दुर्भाग्य से लगता नहीं है, क्योंकि ओपी चार वर्षों में साइट पर नहीं है।
जो कैनेडी

जवाबों:


429

जैसा कि दूसरों ने कहा है, Dir::foreachयहाँ एक अच्छा विकल्प है। हालांकि, ध्यान दें कि Dir::foreachऔर Dir::entriesहमेशा शामिल होंगे .और ..(वर्तमान और माता पिता निर्देशिका)। तुम्हें पता है, उन पर काम करना चाहते हैं आम तौर पर नहीं होगा तो आप उपयोग कर सकते हैं Dir::each_childया Dir::children(के रूप में ma11hew28 ने सुझाव दिया ) या कुछ इस तरह करते हैं:

Dir.foreach('/path/to/dir') do |filename|
  next if filename == '.' or filename == '..'
  # Do work on the remaining files & directories
end

Dir::foreachऔर Dir::entries(और साथ ही Dir::each_childऔर Dir::children) भी छिपा फ़ाइलें और निर्देशिका में शामिल हैं। अक्सर यह वही है जो आप चाहते हैं, लेकिन अगर ऐसा नहीं है, तो आपको उन्हें छोड़ने के लिए कुछ करने की जरूरत है।

वैकल्पिक रूप से, आप यह देखना चाहते हैं कि Dir::globकौन सा साधारण वाइल्डकार्ड मिलान प्रदान करता है:

Dir.glob('/path/to/dir/*.rb') do |rb_filename|
  # Do work on files & directories ending in .rb
end

12
Dir.foreachयदि निर्देशिका में बड़ी संख्या में फ़ाइलें हैं, तो उपयोग करें !
तिलो

5
धन्यवाद! छोटा मॉड इसे और बेहतर बनाने के लिए:next if File.directory? item
mr.buttons

@ mr.buttons जो हमेशा सही काम नहीं करेगा। कभी-कभी लोग निर्देशिकाओं के साथ-साथ फाइलों पर भी काम करना चाहते हैं । मैंने विशेष लिस्टिंग से बचने के लिए कोड दिया क्योंकि .या ..लोग लगभग हमेशा उन दोनों को अनदेखा करना चाहते हैं।
टेलीमेकस

3
@Tilo: बस ब्याज से बाहर, थोड़ा और अधिक विस्तार से समझाने की परवाह क्यों? :)
मटकाजा

11
@mkataja Dir.foreachएक (संभावित रूप से विशाल) फ्रंट अप (जो Dir.globकरता है) का निर्माण करने के बजाय पुनरावृत्त करता है। इसलिए यदि निर्देशिका वास्तव में बहुत बड़ी है, तो यह प्रदर्शन में अंतर ला सकती है। सामान्य परिस्थितियों में आप नोटिस नहीं करेंगे, लेकिन तनाव की स्थिति में, यह बिल्कुल मायने रख सकता है।
टेलीमेकस

99

पढ़ने में आसान होने के लिए यह मेरा पसंदीदा तरीका है:

Dir.glob("*/*.txt") do |my_text_file|
  puts "working on: #{my_text_file}..."
end

और आप सबडिडर में सभी फाइलों पर काम करने के लिए इसे बढ़ा भी सकते हैं:

Dir.glob("**/*.txt") do |my_text_file| # note one extra "*"
  puts "working on: #{my_text_file}..."
end

30

Dir ने निर्देशिका से सभी फ़ाइलों की एक सरणी प्राप्त करने के लिए सिंटैक्स भी छोटा किया है:

Dir['dir/to/files/*'].each do |fname|
    # do something with fname
end

क्या इस कोड में निर्देशिकाओं को भी fnameपुनरावृत्तियों के साथ उपयोग करने से रोकता है ?
kayleeFrye_onDeck


13

लाईब्रेरी को इस कार्य के लिए विशेष रूप से डिज़ाइन किया गया है: https://ruby-doc.org/stdlib-2.5.1/libdoc/find/rdoc/Find.html

require 'find'
Find.find(path) do |file|
  # process
end

यह एक मानक रूबी पुस्तकालय है, इसलिए यह उपलब्ध होना चाहिए


1
File.findजहाँ तक आप इसे दे सकते हैं, से पुनरावृत्ति के रूप में जहाँ तक यह कर सकते हैं नीचे जाता है। मुझे यकीन नहीं है कि ओपी क्या चाहता है।
टेलीमेकस

मैं उस विधि का उपयोग करने के लिए नहीं लगता - Find.find क्या मुझे लाइब्रेरी डाउनलोड करने की आवश्यकता है ot में यह कार्यक्षमता शामिल है?
नीला-आकाश

@ user470184: "ढूंढें" एक मानक रूबी लाइब्रेरी है और इसे डिफ़ॉल्ट रूबी इंस्टॉलेशन के साथ उपलब्ध होना चाहिए। हालाँकि, आपको इसका उपयोग करने से पहले "खोजे" की आवश्यकता है।
फैसल

1
@Faisal सकते हैं मैं की तरह ग्लोब पैटर्न पारित *.rbकरने के लिएfind()
Ashhar हसन

7

मुझे यह पसंद है, जिसका उल्लेख ऊपर नहीं किया गया है।

require 'pathname'

Pathname.new('/my/dir').children.each do |path|
    puts path
end

लाभ यह है कि आपको एक स्ट्रिंग के बजाय एक पाथनाम ऑब्जेक्ट मिलता है, जिससे आप आगे और पीछे के साथ उपयोगी सामान कर सकते हैं।


3
Dir.new('/my/dir').each do |name|
  ...
end

1
Dir.new ('/ / my / dir') के अलावा Dir.entries ('/ my / dir') भी है, लेकिन Dir.foreach () थोड़ा अधिक सक्सेसफुल है।
द टिन मैन

5
@ZED भी पूरे सरणी को एक ही बार में Dir.foreachबनाते समय पुनरावृत्त Dir.entriesकरता है। इसलिए यदि निर्देशिका अपार है, तो यह एक मेमोरी हिट से कम है। (आम तौर पर एक बड़ी बात नहीं है, शायद, लेकिन अभी भी ...)
टेलीमेकस

2

स्किप करने के लिए .& का ..उपयोग कर सकते हैं Dir::each_child

Dir.each_child('/path/to/dir') do |filename|
  puts filename
end

Dir::children फ़ाइल नाम की एक सरणी देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.