76

I have a situation where I'm trying to use grunt to lint a codebase, excluding specific folders.

grunt uses minimatch (similar to bsdglob) under the hood to match files, but I can't seem to figure out how to do a .gitignore style exclude of a folder.

I'd like to ingest this:

ignoreme

and match these:

/folder/path/here/to/something/ok.js
/another/folder/path.js
/test.js

but not match these:

/folder/ignoreme/something.js
/folder/path/here/to/ignoreme/metoo/file.js

This will match everything, including ignoreme:

/**/*.js

So I figured I could do something like:

/**/!(ignoreme)/**/*.js

but that matches files in the ignoreme folder.

I'm used to regexes, but can't seem to figure out how to repeat a pattern or something here - I also tried stuff like:

/(!(ignoreme)|*)*/*.js

hoping the container would repeat, but that doesn't work, it just fails to match everything.

Any way to either pass a regex to grunt file paths, or make this work for me?

Update:

Here's how I'm currently dealing with this issue:

var pattern = /\/ignoreme\//
var files = grunt.file.expandFiles(arrayOfFilesPassedToMinimatch).filter(function(f){
  return !pattern.test(f)
})

I'd still be interested if folder excludes are possible in minimatch.

Jesse
  • 10,370
  • 10
  • 62
  • 81
  • 2
    Using `map` is results in `files` containing a array of `TRUE` and `FALSE` values. `filter` will correctly set `files` to be a list of filtered paths. – deefour Nov 21 '12 at 15:18
  • Right you are, must have typed at night. Updated the code sample to work. – Jesse Jan 30 '13 at 05:04

1 Answers1

149

In the currently-in-development version 0.4.0a, the grunt.file.expand method now supports exclusions, and does so in an arguably less complex way than the underlying minimatch matching library. This is possible because grunt.file.expand accepts multiple patterns (whereas minimatch only accepts one).

From the grunt.file.expand documentation:

This method accepts either comma separated wildcard patterns or an array of wildcard patterns. Paths matching patterns that begin with ! will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.

That means you could specify ['/**/*.js', '!**/ignoreme/**'] and while the first pattern would add all .js files to the result set, the second pattern would then remove all /ignoreme/ files from the result set.

Take a look at the grunt.file.match unit tests if you're really curious.

Note that the version of grunt offering this functionality hasn't officially been released, but if you're interested in using it in a project, see the When will I be able to use in-development feature 'X'? FAQ entry.

R. Oosterholt
  • 7,720
  • 2
  • 53
  • 77
Cowboy Ben Alman
  • 1,941
  • 1
  • 13
  • 10
  • Thanks so much for the reply! This looks like a much more elegant solution to my issue - I'll wait for a stable release, but I'll switch when it's out! – Jesse Sep 29 '12 at 19:04
  • 14
    Worth noting: exclusion patterns only work if they come *AFTER* whatever-it-is-they-exclude has been matched by an inclusion pattern. Was confused by putting my exclusion patterns first. – Justin Searls Jul 05 '13 at 04:04
  • 3
    `grunt watch --verbose` to see which files are being watched – Shanimal Aug 12 '13 at 18:58
  • That's awesome. Thought I would have to write some weird filter just to ignore a file. – Jeff Dec 16 '13 at 16:14