रूबी के साथ एक फ़ोल्डर से सभी फ़ाइलों के नाम प्राप्त करें


जवाबों:


537

आपके पास शॉर्टकट का विकल्प भी है

Dir["/path/to/search/*"]

और यदि आप किसी भी फ़ोल्डर या उप-फ़ोल्डर में सभी रूबी फाइलें ढूंढना चाहते हैं:

Dir["/path/to/search/**/*.rb"]

5
या आप Dir :: glob ()
Yoann Le Touche

2
इसके अलावा, का उपयोग ./...करने के बजाय~/
मिन्ह Triết

5
इसे क्यों पसंद किया जाता है
BvuRVKyUVlViVIc7 11

1
@MinhTriet क्या करता है? यह क्या बेहतर है?
स्टीफनमुर्डोक

9
@marflar - का ./अर्थ है वर्तमान निर्देशिका, जबकि /रूट माउंट बिंदु है, और ~/उपयोगकर्ता की होम निर्देशिका है। यदि आप पूरी परियोजना को कहीं और स्थानांतरित करते हैं, तो पहला काम करेगा, लेकिन अन्य दो शायद नहीं करेंगे।
मिरीचन

170
Dir.entries(folder)

उदाहरण:

Dir.entries(".")

स्रोत: http://ruby-doc.org/core/classes/Dir.html#method-c-entries


15
ऐसा लगता है कि वह एसओ का उपयोग उन सवालों के जवाबों का दस्तावेजीकरण करने के लिए कर रहा है जो उसने अभी-अभी पूछे हैं। एक प्रकार का ज्ञापन, मुझे लगता है। इसके साथ बहुत गलत नहीं देखा जा सकता है - आखिरकार, भले ही यह थोड़ा अधूरा हो ( Dir#globउदाहरण के लिए, शायद उदाहरण के लिए उल्लेख किया गया है), किसी और को वास्तव में अच्छा जवाब पोस्ट करने से रोकने के लिए कुछ भी नहीं है। 'बेशक, मैं ज्यादातर एक "ग्लास आधा भरा हुआ" एक आदमी हूँ ...
माइक वुडहाउस

1
@ माइक: चीजों की भव्य योजना में, यह शायद एक बड़ी बात नहीं है। और जैसा कि आप कहते हैं कि यदि प्रश्न और उत्तर अच्छे थे, तो यह साइट के लिए एक समग्र परिणाम हो सकता है। लेकिन यहाँ प्रश्न और उत्तर दोनों ही इतने न्यूनतम हैं कि यह विशेष रूप से उपयोगी नहीं लगता है।
टेलीमेकस

17
@Telemachus मैं Dirशायद ही कभी उपयोग करता हूं, और हर बार जब मुझे इसकी आवश्यकता होती है तो मुझे दस्तावेज़ीकरण पढ़ना पड़ता है। मैंने अपना प्रश्न और उत्तर यहाँ पोस्ट किया है ताकि मैं इसे बाद में पा सकूँ, और शायद उसी प्रश्न के साथ किसी की मदद भी कर सकूँ। मुझे लगता है कि मैंने एसओ पॉडकास्ट में सुना है कि इस तरह के व्यवहार में कुछ भी गलत नहीं है। यदि आपके पास बेहतर उत्तर है, तो कृपया इसे पोस्ट करें। मैंने जो जाना है उसे पोस्ट किया है, मैं रूबी निंजा नहीं हूं। मैं नियमित रूप से सबसे अधिक वोटों के साथ उत्तर स्वीकार करता हूं।
लज्जको फिलीपिन

इस तुलना में एक बेहतर विकल्प हो सकता है Dir[]या Dir.globजब तर्क एक चर है। जब path = '/tmp', तुलना करें: Dir.glob("#{path}/*")बनाम Dir.entries(path)। रिटर्न मान थोड़े अलग हैं ("।", ".."), लेकिन बाद वाले को त्वरित नज़र में घिसना आसान है।
बेंजामिन

92

निम्नलिखित स्निपेट बिल्कुल एक निर्देशिका के अंदर फाइलों का नाम दिखाता है, उपनिर्देशिकाओं को छोड़ देता है और ".", ".."बिंदीदार फ़ोल्डर:

Dir.entries("your/folder").select {|f| !File.directory? f}

19
...select {|f| File.file? f}स्पष्ट अर्थ और छोटे वाक्यविन्यास के लिए भी कर सकते हैं ।
ऑटोमियो

2
@squixy क्या आप इसे सही ढंग से लिखने ?:Dir.entries("your/folder").select {|f| File.file? f}
Automatico

9
हां। !File.directory?काम कर रहा है लेकिन File.file?नहीं।
कामिल लेलोनेक

2
@squixy मुझे भी यही समस्या थी, मेरे मामले में मुझे पूरा रास्ता प्रदान करने की आवश्यकता है न कि केवल फ़ाइल का नाम Dir.foreach द्वारा लौटाया गया
TheLukeMcCarthy

6
.reject {|f| File.directory? f}से साफ लगता है .select{|f| !File.directory? f}। ओह, और अब मैं पहली टिप्पणी देखता हूं ... अच्छा भी।
इयान

36

सभी फ़ाइलें (केवल सख्ती से फ़ाइलें) प्राप्त करने के लिए:

Dir.glob('path/**/*').select{ |e| File.file? e }

या कुछ भी जो एक निर्देशिका नहीं है ( File.file?गैर-नियमित फ़ाइलों को अस्वीकार कर देगा):

Dir.glob('path/**/*').reject{ |e| File.directory? e }

दूसरा तरीका

Find#findपैटर्न-आधारित लुकअप विधि का उपयोग करना Dir.globवास्तव में बेहतर है। देखें करने के लिए इस सवाल का जवाब "रूबी में रिकर्सिवली सूची निर्देशिकाएँ करने के लिए एक-लाइनर?"


18

यह मेरे लिए काम करता है:

यदि आप छिपी हुई फ़ाइलें नहीं चाहते हैं [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यूनिक्स पर, मैं विंडोज के बारे में नहीं जानता



9

व्यक्तिगत रूप से, मैंने इसे एक फ़ोल्डर में फ़ाइलों पर लूपिंग के लिए सबसे उपयोगी पाया, आगे की ओर देख सुरक्षा:

Dir['/etc/path/*'].each do |file_name|
  next if File.directory? file_name 
end

9

यह एक निर्देशिका में फ़ाइलों को खोजने के लिए एक समाधान है:

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

6

एक निर्देशिका में सभी फ़ाइल नाम प्राप्त करते समय, इस स्निपेट का उपयोग दोनों निर्देशिका [ ., ..] और छिपी हुई फाइलों को अस्वीकार करने के लिए किया जा सकता है , जो एक के साथ शुरू होती हैं.

files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}

Dir.entriesस्थानीय फ़ाइल नाम देता है, न कि पूर्ण फ़ाइल पथ। दूसरी ओर, File.directory?एक पूर्ण फ़ाइल पथ की अपेक्षा करता है। यह कोड अपेक्षा के अनुरूप काम नहीं करता है।
नाथन

यह अजीब है कोड आपके मामले में काम नहीं करता है। जैसा कि यह एक कोड है जिसका मैंने लाइव ऐप में उपयोग किया है जो ठीक काम करता है। मैं अपना कोड और पोस्ट यहाँ देखूंगा अगर मेरे मूल काम कोड से कुछ गायब है :)
लाहिरु

1
@ नथन एक स्पष्टीकरण के लिए मेरा जवाब देखें

5

यह कोड केवल उनके एक्सटेंशन (वैश्विक पथ के बिना) के साथ फ़ाइल नाम देता है

Dir.children("/path/to/search/")

4

यह मेरे लिए काम करता है:

Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }

Dir.entriesस्ट्रिंग्स की एक सरणी देता है। फिर, हमें फ़ाइल का पूरा पथ प्रदान करना होगा File.file?, जब तक dirकि हमारी वर्तमान कार्यशील निर्देशिका के बराबर न हो । इसलिए ऐसा है File.join()


1
आपको "बाहर करने की आवश्यकता है।" और प्रविष्टियों से ".."
एडगर ऑर्टेगा

3

आप भी उपयोग करना चाहते हैं Rake::FileList(बशर्ते आपके पास rakeनिर्भरता हो):

FileList.new('lib/*') do |file|
  p file
end

एपीआई के अनुसार:

FileLists आलसी हैं। जब फ़ाइल को सूची में शामिल करने के लिए संभावित फ़ाइलों के लिए ग्लोब पैटर्न की एक सूची दी जाती है, तो फ़ाइलों को खोजने के लिए फ़ाइल संरचनाओं को खोजने के बजाय, एक फाइललिस्ट बाद के उपयोग के लिए पैटर्न रखता है।

https://docs.ruby-lang.org/en/2.1.0/Rake/FileList.html


1

यदि आप सिमिलिंक , उपयोग सहित फ़ाइल नाम का एक सरणी प्राप्त करना चाहते हैं

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')यदि आप सभी फ़ाइलों को पुन: प्राप्त करना चाहते हैं , तो इसका उपयोग करें ।


या सिर्फ उपयोग करें*.*
रिचर्ड पेक


1

इस सूत्र में सुझावों के अलावा, मैं यह उल्लेख करना चाहता था कि अगर आपको डॉट फाइलें (.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 का उपयोग कर रहा था।



0
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

निर्देशिका और सभी उपनिर्देशिकाओं से फ़ाइल के सापेक्ष पथ लौटाता है


0

IRB संदर्भ में, आप वर्तमान निर्देशिका में फ़ाइलों को प्राप्त करने के लिए निम्नलिखित का उपयोग कर सकते हैं:

file_names = `ls`.split("\n")

आप अन्य निर्देशिकाओं पर भी यह काम कर सकते हैं:

file_names = `ls ~/Documents`.split("\n")

यह समाधान मेरे लिए काम कर रहा है क्योंकि मेरे पास पुराने रूबी संस्करण के साथ एक विरासत समाधान है जो Dir.children कमांड का समर्थन नहीं करता है
Ciprian Dragoe
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.