Fixing the issue with globstar paths (**/*) not working when running an npm script.

2 min read Original article ↗

Fixing the issue with globstar paths (**/*) not working when running an npm script.

🚧 Issue Description

If you've ever run a script like npm run test from your package.json:

{
  "scripts": {
    "test": "node --test src/**/*.test.js"
  }
}

You'll notice we are using a globstar here src/**/*.test.js.

The thing is, on Linux, npm run runs scripts with sh by default.

By default, sh doesn't support globstar paths like **/*. So you'll notice that it'll only find files one directory deep, and will treat src/**/*.test.js as if you only wrote src/*/*.test.js.

This is a major pitfall that can easily go by undetected. For example, imagine your CI skipping 90% of your tests since it was looking at only some of the directories!

✅ Resolution Steps

⚠️ NOTE: This was only tested on Linux, and was not tested on Windows or Mac.

To fix this, figure out how to enable globstar in your shell. Or do what I did and just update npm to use zsh as the default shell for running scripts.

Unlike sh, zsh understands and expands globstar paths by default.

Here's how to do that:

  1. First run npm config ls -l | grep shell to see what config you have. It'll probably say:
script-shell = null
shell = "/bin/bash"
  1. Now, run npm config set script-shell=zsh to update the script-shell option to use zsh.

  2. Confirm that the update worked. Run npm config ls -l | grep shell. It'll probably say:

; script-shell = null ; overridden by user
shell = "/bin/bash"
script-shell = "zsh"
  1. Now, try using globstar paths again in your scripts. All the matching files should be discovered now by the shell (even several subdirectories deep).

You're all set! 😌

The problem now is... remembering to do this everywhere you use npm. 😢

(GitHub Codespaces, other laptop, work computer..................)

By the way, many tools that you would use within npm run scripts, like mocha, support quoting the globstar in the script, like 'src/**/*.test.js', in which case they will perform the globstar matching for you, not relying on the shell you are using. This is a great solution! Use this wherever possible.

Unfortunately, some tools don't support this yet, like the native Node.js v20 test runner node --test. When Node.js supports this, like node --test 'src/**/*.test.js', I won't really need this hack anymore!