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

21,478

Solution 1

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.

Solution 2

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.

Solution 3

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

Solution 4

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

Solution 5

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
Share:
21,478

Related videos on Youtube

jarjar
Author by

jarjar

Software Engineer

Updated on July 09, 2022

Comments

  • jarjar
    jarjar almost 2 years

    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.

  • SimplGy
    SimplGy over 11 years
    I can't figure out how to use .reject correctly. Does it not support the same wildcards as .glob? Would like to do ...reject{ |f| f['*/.tmpl.html'] }.each {...
  • SimplGy
    SimplGy over 11 years
    also no... .reject{ |f| File.fnmatch('**.tmpl.html', f) }.each {... :)
  • SimplGy
    SimplGy over 11 years
    Got it, my understanding of path matching was wrong. double star doesn't mean it will match in any directory, you still need a context directory. Works: .reject { |f| File.fnmatch('../../../main/webapp/**.tmpl.html', f)
  • SimplGy
    SimplGy over 10 years
    I just came back to the answer again, forgot I'd used it already. Wish I could vote it up twice :)
  • three
    three almost 9 years
    same goes for files in case thats needed too: Dir.glob "views/{[!partial_]}*.slim" Explained: You're reading your views dir and every fiule that starts with partial_ has to be excluded. The remaining .slim files will be listed.
  • Anwar
    Anwar almost 9 years
    Can you explain a bit? I am trying to exclude a folder named to_delete but only files with name starting with t,o,d,e,l,t are being excluded.
  • Eric Hu
    Eric Hu almost 8 years
    WARNING! This negation is not quite accurate. Ruby's implementation of [!...] matches this description on Wikipedia. [!errors/] matches one character that is not e,r, o, s, or /. [!e][!r][!r][!o][!r][!s][!/] would match strings that don't begin with "errors/", however, it would not match strings shorter than 7 chararacters. (You can verify this by making some test folders named a, aa, ab, etc. in irb and using Dir.glob to list them).
  • Djidiouf
    Djidiouf over 4 years
    How can you make it work for a specific hidden directory that you want to exclude?