jarjar
jarjar

Reputation: 1701

Is there a way to glob a directory in Ruby but exclude certain directories?

I want to glob a directory to post-process header files. Yet I want to exclude some directories in the project. Right now the default way is...

Dir["**/*.h"].each { |header|
    puts header
}

Seems inefficient to check each header entry manually if it's in an excluded directory.

Upvotes: 32

Views: 25065

Answers (6)

Naftulee
Naftulee

Reputation: 21

this is similar to a few other answers just written a bit differently

Ill create an array that can be passed to a .each iteration or something else.

release_safelist = Dir.glob('*').reject{ |file|
  (file == "softlinks") || (file == "ci") || (file.include? "SNAPSHOT")
}

In this case im creating an array without files/dir named either ci, softlinks, or containing SNAPSHOT

Upvotes: 2

grosser
grosser

Reputation: 15097

files = Dir.glob(pattern)
files -= Dir.glob("#{exclude}/**/*")

Upvotes: 11

Jordon Bedwell
Jordon Bedwell

Reputation: 3247

I know this is 4 years late but for anybody else that might run across this question you can exclude from Dir the same way you would exclude from Bash wildcards:

Dir["lib/{[!errors/]**/*,*}.rb"]

Which will exclude any folder that starts with "errors" you could even omit the / and turn it into a wildcard of sorts too if you want.

Upvotes: 66

Theo
Theo

Reputation: 132862

There's FileList from the Rake gem (which is almost always installed by default, and is included in the standard library in Ruby 1.9):

files = FileList['**/*.h'].exclude('skip_me')

FileList has lots of functionality for working with globs efficiently.

You can find the documentation here: http://rake.rubyforge.org/classes/Rake/FileList.html

Upvotes: 18

the Tin Man
the Tin Man

Reputation: 160551

Don't use globbing, instead use Find. Find is designed to give you access to the directories and files as they're encountered, and you programmatically decide when to bail out of a directory and go to the next. See the example on the doc page.

If you want to continue using globbing this will give you a starting place. You can put multiple tests in reject or'd together:

Dir['**/*.h'].reject{ |f| f['/path/to/skip'] || f[%r{^/another/path/to/skip}] }.each do |filename|
  puts filename
end

You can use either fixed-strings or regex in the tests.

Upvotes: 31

Mark Thomas
Mark Thomas

Reputation: 37517

One way:

require 'find'

ignores = ['doc','test','specifications']

Find.find(ENV['HOME']) do |path|
  name = File.basename(path)
  if FileTest.directory?(path)
    if ignores.include?(name)
      Find.prune
    else
      next
    end
  else
    puts path if name =~ /.h$/
  end
end

Upvotes: 4

Related Questions