Ruby를 사용하여 폴더에서 모든 파일 이름 가져 오기


답변:


537

바로 가기 옵션도 있습니다

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

폴더 또는 하위 폴더에서 모든 Ruby 파일을 찾으려면 다음을 수행하십시오.

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

5
또는 당신은 디렉터리와 같은 작업을 수행 할 수 있습니다 : 글로브 ()
요안 르 감동적

2
또한, ./...대신 사용하십시오~/
Minh Triet

5
이것이 왜 선호됩니까?
BvuRVKyUVlViVIc7

1
@MinhTriet 그게 뭐죠? 바람직한 것은 무엇입니까?
stephenmurdoch

9
@marflar- ./현재 디렉토리를 의미하는 반면 /루트 마운트 지점이며 ~/사용자의 홈 디렉토리입니다. 전체 프로젝트를 다른 곳으로 옮기면 첫 번째 프로젝트는 작동하지만 다른 두 프로젝트는 효과가 없습니다.
mirichan

170
Dir.entries(folder)

예:

Dir.entries(".")

출처 : http://ruby-doc.org/core/classes/Dir.html#method-c-entries


15
그가 방금 질문 한 질문에 대한 답변을 문서화하기 위해 SO를 사용하고있는 것 같습니다. 일종의 메모라고 생각합니다. 이것으로 많은 것을 잘못 볼 수는 없습니다. 결국 비록 조금 불완전하지만 ( Dir#glob예를 들어 언급되었을 수도 있습니다) 다른 사람이 정말 좋은 답변을 게시하는 것을 막을 수있는 것은 없습니다. '과정, 나는 주로 "유리 반 전체"일종의 남자 ...
Mike Woodhouse

1
@ 마이크 : 대단한 계획에서 아마도 큰 문제는 아닙니다. 질문과 답변이 좋으면 사이트 전체에 도움이 될 수 있습니다. 그러나 여기에 질문과 답변이 너무 작아서 특히 유용하지 않습니다.
Telemachus

17
@ Telemachus 나는 Dir거의 사용 하지 않으며 필요할 때마다 문서를 읽어야합니다. 내 질문과 답변을 여기에 게시하여 나중에 찾을 수 있으며 같은 질문을 가진 사람을 도울 수도 있습니다. SO 팟 캐스트에서 그런 행동에는 아무런 문제가 없다고 들었습니다. 더 나은 답변이 있으면 게시하십시오. 나는 내가 아는 것을 게시했다. 나는 루비 닌자가 아니다. 나는 가장 많은 표를 얻은 답변을 정기적으로 받아들입니다.
Željko Filipin

이것은 인수가 변수 일 때보 다 Dir[]또는 더 나은 옵션 일 수 있습니다 Dir.glob. 때 path = '/tmp', 비교 : Dir.glob("#{path}/*")Dir.entries(path). 반환 값은 약간 다르지만 ( ".", "..") 후자는 한 눈에 파악하기가 더 쉽습니다.
Benjamin Oakes

92

다음 조각은 정확히 디렉토리 내 파일을 건너 뛰는 하위 디렉토리 및 이름 표시 ".", ".."점으로 구분 된 폴더를 :

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

19
...select {|f| File.file? f}더 명확한 의미와 더 짧은 구문을 위해 할 수도 있습니다 .
Automatico

2
@squixy 올바르게 작성 했습니까? :Dir.entries("your/folder").select {|f| File.file? f}
Automatico

9
네. !File.directory?작동하지만 작동하지 File.file?않습니다.
Kamil Lelonek

2
@ squixy 나는 같은 문제가 있었다, 내 경우에는 Dir.foreach에 의해 반환 된 파일 이름뿐만 아니라 전체 경로를 제공해야합니다
TheLukeMcCarthy

6
.reject {|f| File.directory? f}보다 깨끗해 보입니다 .select{|f| !File.directory? f}. 아, 이제 첫 번째 의견도 보았습니다 ... 또한 좋습니다.
Ian

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 는 숨겨진 파일을 반환하고 와일드 카드 별표 (디렉토리 이름으로 변수를 전달할 수 있음)는 필요하지 않지만 기본 이름을 직접 반환하므로 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유닉스에서 나는 Windows에 대해 모른다



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?절대 파일 경로가 필요합니다. 이 코드는 예상대로 작동하지 않습니다.
Nathan

귀하의 경우 코드가 작동하지 않는 것이 이상합니다. 이 코드는 라이브 앱에서 사용한 코드이므로 정상적으로 작동합니다. 원래 작업 코드에서 누락 된 것이 있으면 코드를 다시 확인하고 여기에 게시하겠습니다. :)
Lahiru

1
@Nathan 설명에 대한 내 대답보기


4

이것이 나를 위해 작동하는 것입니다.

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

Dir.entries문자열 배열을 반환합니다. 그런 다음 현재 작업 디렉토리와 동일 File.file?하지 않은 경우 파일의 전체 경로를 제공해야합니다 dir. 이것이 바로이 이유 File.join()입니다.


1
"."을 제외해야합니다. 및 항목에서 ".."
Edgar Ortega

3

다음을 사용하고 싶을 수도 있습니다 Rake::FileList( rake종속성이있는 경우).

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

API에 따르면 :

FileLists가 게으르다. 파일 목록에 포함 할 수있는 파일에 대한 glob 패턴 목록이 제공되면 파일 구조를 검색하여 파일을 찾는 대신 FileList는 나중에 사용하기 위해 패턴을 보유합니다.

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')하십시오.


아니면 그냥 사용하십시오*.*
Richard Peck


1

이 스레드의 제안 외에도 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이 경우 파일이 디렉토리인지 확인하기 위해 파일의 절대 경로를 다시 작성해야했기 때문에 시간이 조금 더 걸리지 만 재귀 적 인 경우에도 다른 옵션보다 계속 더 오래 걸리고 있습니다. 이것은 모두 OSX에서 루비 2.5.1을 사용했습니다.


1

한 가지 간단한 방법은 다음과 같습니다.

dir = './' # desired directory
files = Dir.glob(File.join(dir, '**', '*')).select{|file| File.file?(file)}

files.each do |f|
    puts f
end

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.