Search code examples
javascriptnode.jsglob

What's wrong with my glob?


I'm trying to write a glob for something that uses minimatch and having trouble excluding the files I want to. Here's a test case:

const glob = 'src/js/*!(test|stub).js' // this is the glob I'm trying to work out

const shouldMatch = [
  'src/js/foo.js',
  'src/js/bar.js',
  'src/js/baz.js',
]

const shouldNotMatch = [
  'src/js/foo.test.js',
  'src/js/bar.stub.js',
  'src/baz/blob.js',
]

const all = shouldMatch.concat(shouldNotMatch)

const matched = minimatch.match(all, glob) // https://www.npmjs.com/package/minimatch

expect(matched).toEqual(shouldMatch) // https://npmjs.com/package/expect

The output with this is:

"Error: Expected [ 'src/js/foo.js', 'src/js/bar.js', 'src/js/baz.js', 'src/js/foo.test.js', 'src/js/bar.stub.js' ] to equal [ 'src/js/foo.js', 'src/js/bar.js', 'src/js/baz.js' ]

You can see a live version of this here.

As you can see, it's including both the test and the stub files. What does my glob need to be so those files are excluded?


Solution

  • This is a common mistake with the !(...) syntax. Imagine something like this:

    ls *!(.png|.jpg)

    This doesn't do what we want because the .png and .jpg are matched by the *. So once we get to !(.png|.jpg), the string is null.

    To fix it, we can do:

    ls !(*.png|*.jpg)

    Thus, to fix your example:

    const glob = 'src/js/!(*test|*stub).js'

    Here's a working example