npm glob pattern不匹配子目录

时间:2015-08-14 19:09:09

标签: node.js npm mocha package.json

在我的package.json中,我有一个脚本块,使用**/*Test.js来匹配文件。通过npm运行时,它们与子目录不匹配多个级别。在命令行上直接执行时,它们按预期工作。

任何人都可以解释发生了什么,并提供解决方法或解决方案吗?

package.json

{
  "name": "immutable-ts",
  "scripts": {
    "test": "echo mocha dist/**/*Test.js",
  }
}

执行

% npm run test

> immutable-ts@0.0.0 test:unit .../immutable-ts
> echo mocha dist/**/*Test.js

mocha dist/queue/QueueTest.js dist/stack/StackTest.js

% echo mocha dist/**/*Test.js

mocha dist/queue/QueueTest.js dist/stack/StackTest.js dist/tree/binary/BinaryTreeTest.js

% ls dist/**/*                                                                                                                                                                                          

dist/collections.js  dist/queue/QueueTest.js  dist/tree/binary/BinaryTree.js      dist/immutable.js.map        dist/stack/Stack.js.map             dist/tree/binary/BinaryTreeTest.js.map
dist/immutable.js    dist/stack/Stack.js      dist/tree/binary/BinaryTreeTest.js  dist/queue/Queue.js.map      dist/stack/StackTest.js.map
dist/queue/Queue.js  dist/stack/StackTest.js  dist/collections.js.map             dist/queue/QueueTest.js.map  dist/tree/binary/BinaryTree.js.map

3 个答案:

答案 0 :(得分:30)

解决方案

更改脚本,以便保护传递给Mocha的内容免受shell的扩展:

"scripts": {
    "test": "mocha 'dist/**/*Test.js'",
 }

请注意mocha的参数周围的单引号。

解释

此问题可以在不使用外部工具的情况下修复。问题的根本原因是npm使用sh作为运行脚本命令的shell。

绝大多数情况下,当一个* nix进程启动一个shell时,它将启动sh,除非有东西告诉它不这样做。您为登录设置的shell首选项不构成一种方式,否则就会告诉它#34;。因此,如果您有zsh作为登录shell,则npm不会使用zsh

sh的那些不包含sh应该提供的任何扩展的实现不会以您希望的方式理解** glob。据我所知,它被解释为*。但是, Mocha使用其globs的JavaScript实现解释传递给它的路径。因此,您可以通过sh保护您的全局不被解释来解决此问题。请考虑以下package.json

{
  "name": "immutable-ts",
  "scripts": {
    "bad": "mocha test/**/*a.js",
    "good": "mocha 'test/**/*a.js'",
    "shell": "echo $0"
  }
}

shell脚本只是为了检查运行脚本的shell。如果您运行它,您应该看到sh

现在,给出以下树:

test/
├── a.js
├── b.js
├── x
│   ├── a
│   │   ├── a.js
│   │   └── b.js
│   ├── a.js
│   └── b
│       └── a.js
└── y
    ├── a.js
    └── q

所有a.jsb.js个文件都包含it(__filename);。您会得到以下结果:

$ npm run bad

> immutable-ts@ bad /tmp/t2
> mocha test/**/*a.js

  - /tmp/t2/test/x/a.js
  - /tmp/t2/test/y/a.js

  0 passing (6ms)
  2 pending

$ npm run good

> immutable-ts@ good /tmp/t2
> mocha 'test/**/*a.js'

  - /tmp/t2/test/a.js
  - /tmp/t2/test/x/a.js
  - /tmp/t2/test/x/a/a.js
  - /tmp/t2/test/x/b/a.js
  - /tmp/t2/test/y/a.js

  0 passing (5ms)
  5 pending

答案 1 :(得分:2)

您可以在脚本中使用find选项内联-name命令,以替换zsh提供的扩展globbing语法。

在您的情况下,命令将是:

mocha `find dist -type f -name '*Test.js'`

如果你确信自己不会放弃" Test.js"你可以现实地省略-type f部分。在目录名称中。 (一个安全的假设,很有可能,但为了完整起见,我把它包括在内)

答案 2 :(得分:-1)

glob扩展实际上是由shell完成的,这就是它从命令行运行的原因。

您可以执行mocha --recursive并指向您的测试目录。