하나의 디렉토리에있는 모든 파일을 반복


274

루비로 루프를 작성하여 각 파일에서 코드 블록을 실행할 수 있습니까?

나는 루비를 처음 접했고 이것을 수행하는 방법은 각 루프를 수행한다는 결론을 내렸다.
루비 파일은 반복하려는 디렉토리와 다른 디렉토리에서 실행됩니다.

시도했지만 Dir.foreach작동하지 못했습니다.


2
작동 시키려고했을 때 어떤 일이 일어 났는지 지정할 수 있습니까? 어떤 정확한 코드를 시도 했습니까 (또는 긴 경우 관련 청크)? 어떤 오류 메시지가 나타 났습니까? Dir.foreach디렉토리의 내용을 반복하여 다른 일이 많이 일어나고 있습니다.
Telemachus

3
디렉토리 내의 파일 만 원하는 경우 디렉토리 내용을 반복 할 때 파일을 테스트하는 것을 잊지 마십시오. do_something_with(entry) if File.file?(entry)
glenn jackman

3
'img/*.{jpg,png,gif,jpeg}'여러 확장을 잡는 데 사용 합니다.
Benjamin Crouzier

OP가 4 년 이상 사이트에 없었기 때문에 @ChrisPeters는 유감스럽게 보이지 않습니다.
Joe Kennedy

답변:


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::foreachDir::entries( Dir::each_childDir::children)에도 숨겨진 파일 및 디렉토리가 포함됩니다. 종종 이것이 당신이 원하는 것이지만, 그렇지 않은 경우에는 건너 뛰기 위해 무언가를해야합니다.

또는 Dir::glob간단한 와일드 카드 일치를 제공하는 것을 살펴볼 수도 있습니다 .

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

12
Dir.foreach디렉토리에 많은 수의 파일이있는 경우 사용하십시오 !
Tilo

5
감사! : 소형은 더 나은 만들기 위해 MODnext if File.directory? item
mr.buttons

@ mr.buttons 항상 올바른 것은 아닙니다. 때때로 사람들 은 파일뿐만 아니라 디렉토리 에서 작업하기를 원합니다 . 나는의 특별한 목록을 회피하기위한 코드를했다 .거나 ..사람들이 거의 항상 그 두 가지를 무시해야하기 때문이다.
Telemachus

3
@Tilo : 관심이없는 이유를 좀 더 자세히 설명해 주시겠습니까? :)
mkataja 2016 년

11
@mkataja Dir.foreach는 (잠재적으로) (잠재적으로 거대한) 배열을 구축하는 대신 반복 Dir.glob합니다. 따라서 디렉토리가 실제로 큰 경우 성능 차이가 발생할 수 있습니다. 정상적인 상황에서는 눈치 채지 못하지만 스트레스 상태에서는 절대적으로 중요합니다.
Telemachus 2016 년

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원하는 경로에서 시작하여 가능한 한 재귀 적으로 내려갑니다. OP가 원하는 것이 확실하지 않습니다.
Telemachus

나는 그 방법에 접근 할 수없는 것 같습니다-Find.find? 이 기능이 포함 된 라이브러리를 다운로드해야합니까?
blue-sky

@ user470184 : "찾기"는 표준 루비 라이브러리이며 기본 루비 설치와 함께 사용할 수 있어야합니다. 그러나 사용하려면 "find"가 필요합니다.
파이살

1
@Faisal 수 있습니까처럼 글로브 패턴을 통과 *.rbfind()
Ashhar 하산

7

나는 위에서 언급하지 않은이 것을 좋아합니다.

require 'pathname'

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

장점은 문자열 대신 Pathname 객체를 가져 와서 유용한 작업을 수행하고 더 많이 탐색 할 수 있다는 것입니다.


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

1
Dir.new ( '/ my / dir') 외에도 Dir.entries ( '/ my / dir')도 있지만 Dir.foreach ()는 좀 더 간결합니다.
Tin Man

5
@ZED 또한 전체 배열을 한 번에 구축 Dir.foreach하면서 반복 Dir.entries합니다. 따라서 디렉토리가 엄청 나면 메모리 사용량이 적습니다. (보통 큰 거래는 아니지만 아마도 ...)
Telemachus

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