npm glob 模式不匹配子目录
npm glob pattern not matching subdirectories
在我的 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
glob 扩展实际上是由您 shell 完成的,这就是它在命令行中工作的原因。
您可以 mocha --recursive
并指向您的测试目录。
您可以在脚本中使用 -name
选项内联 find
命令,以替换 zsh 提供的扩展通配符语法。
在您的情况下,命令为:
mocha `find dist -type f -name '*Test.js'`
如果您确信您永远不会将 "Test.js" 放在目录名称中,则可以实际地省略 -type f
部分。 (很可能是一个安全的假设,但为了完整起见,我将其包括在内)
解决方案
更改您的脚本,以便您传递给 Mocha 的内容不会受到 shell:
的扩展
"scripts": {
"test": "mocha 'dist/**/*Test.js'",
}
请注意 mocha
.
参数周围的单引号
说明
无需借助外部工具即可解决此问题。您的问题的根本原因是 npm
使用 sh
作为 shell 将 运行 您的脚本命令。
绝大多数情况下,当 *nix 进程启动 shell 时,它将启动 sh
除非有什么东西告诉它不这样做。您为登录设置的 shell 首选项不构成 "tell it otherwise" 的方式。因此,如果您使用 zsh
作为登录名 shell,则并不意味着 npm
将使用 zsh
.
那些 sh
的实现不包含超出 sh
应该提供的任何扩展,无法按照您希望的方式理解 **
glob。据我所知,它被解释为 *
。但是,Mocha 使用它的 JavaScript globs 实现来解释传递给它的路径。因此,您可以通过保护 glob 不被 sh
. 解释来解决此问题。请考虑以下 package.json
:
{
"name": "immutable-ts",
"scripts": {
"bad": "mocha test/**/*a.js",
"good": "mocha 'test/**/*a.js'",
"shell": "echo [=11=]"
}
}
shell
脚本只是为了让我们可以检查 shell 是什么 运行 脚本。如果你 运行 它,你应该看到 sh
.
现在,给定以下树:
test/
├── a.js
├── b.js
├── x
│ ├── a
│ │ ├── a.js
│ │ └── b.js
│ ├── a.js
│ └── b
│ └── a.js
└── y
├── a.js
└── q
所有 a.js
和 b.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
在我的 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
glob 扩展实际上是由您 shell 完成的,这就是它在命令行中工作的原因。
您可以 mocha --recursive
并指向您的测试目录。
您可以在脚本中使用 -name
选项内联 find
命令,以替换 zsh 提供的扩展通配符语法。
在您的情况下,命令为:
mocha `find dist -type f -name '*Test.js'`
如果您确信您永远不会将 "Test.js" 放在目录名称中,则可以实际地省略 -type f
部分。 (很可能是一个安全的假设,但为了完整起见,我将其包括在内)
解决方案
更改您的脚本,以便您传递给 Mocha 的内容不会受到 shell:
的扩展"scripts": {
"test": "mocha 'dist/**/*Test.js'",
}
请注意 mocha
.
说明
无需借助外部工具即可解决此问题。您的问题的根本原因是 npm
使用 sh
作为 shell 将 运行 您的脚本命令。
绝大多数情况下,当 *nix 进程启动 shell 时,它将启动 sh
除非有什么东西告诉它不这样做。您为登录设置的 shell 首选项不构成 "tell it otherwise" 的方式。因此,如果您使用 zsh
作为登录名 shell,则并不意味着 npm
将使用 zsh
.
那些 sh
的实现不包含超出 sh
应该提供的任何扩展,无法按照您希望的方式理解 **
glob。据我所知,它被解释为 *
。但是,Mocha 使用它的 JavaScript globs 实现来解释传递给它的路径。因此,您可以通过保护 glob 不被 sh
. 解释来解决此问题。请考虑以下 package.json
:
{
"name": "immutable-ts",
"scripts": {
"bad": "mocha test/**/*a.js",
"good": "mocha 'test/**/*a.js'",
"shell": "echo [=11=]"
}
}
shell
脚本只是为了让我们可以检查 shell 是什么 运行 脚本。如果你 运行 它,你应该看到 sh
.
现在,给定以下树:
test/
├── a.js
├── b.js
├── x
│ ├── a
│ │ ├── a.js
│ │ └── b.js
│ ├── a.js
│ └── b
│ └── a.js
└── y
├── a.js
└── q
所有 a.js
和 b.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