不匹配子目录的npm glob模式

时间:2022-09-11 18:46:26

In my package.json, I have a scripts block that uses **/*Test.js to match files. When run via npm, they do not match sub-directories more than one level. When executed on the command line directly, they work as expected.

在我的包。json,我有一个使用**/*测试的脚本块。js文件相匹配。当通过npm运行时,它们不匹配一个以上的子目录。当在命令行上直接执行时,它们会按预期工作。

Can anyone explain what is happening, and provide a workaround or solution?

谁能解释一下发生了什么,并提供一个解决方案吗?

package.json

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

Execution

% 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 个解决方案

#1


25  

Solution

Change your scripts so that what you pass to Mocha is protected from expansion by the shell:

更改您的脚本,以便您传递给Mocha的内容不会被shell扩展:

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

Note the single quotes around the parameter given to mocha.

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

Explanation

This issue is fixable without resorting to external tools. The root cause of your problem is that by npm uses sh as the shell that will run your script commands.

这个问题无需借助外部工具就可以解决。问题的根本原因是npm使用sh作为shell来运行脚本命令。

It is overwhelmingly the case that when a *nix process starts a shell it will start sh unless there is something telling it to do otherwise. The shell preference you set for logins does not constitute a way to "tell it otherwise". So if you have, say, zsh as your login shell, it does not entail that npm will use zsh.

绝大多数情况下,当*nix进程启动shell时,它将启动sh,除非有什么东西告诉它不这样做。您为登录设置的shell首选项并不构成一种“告诉它否则”的方法。因此,如果您有,比方说,zsh作为您的登录shell,并不需要npm使用zsh。

Those implementations of sh that do not include any extensions beyond what sh should provide do not understand the ** glob in the way you want it to. As far as I can tell, it is interpreted as *. However, Mocha interprets the paths passed to it using its a JavaScript implementation of globs. So you can work around the issue by protecting your globs from being interpreted by sh. Consider the following package.json:

那些不包含任何超出sh所应该提供的扩展的sh的实现不理解您想要的方式的** glob。据我所知,它被解释为*。但是,Mocha使用其globs的JavaScript实现来解释传递给它的路径。因此,您可以通过保护您的globs不被sh解释来解决这个问题。

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

The shell script is just so that we can check what shell is running the script. If you run it, you should see sh.

shell脚本只是为了检查哪个shell正在运行脚本。如果你运行它,你应该看到sh。

Now, given the following tree:

现在,考虑到下面这棵树:

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

With all a.js and b.js files containing it(__filename);. You get the following results:

与所有。js和b。js文件包含它(__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

#2


2  

You can inline the find command with the -name option in your scripts to replace the extended globbing syntax provided by zsh.

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

In your case, the command would be:

在你的情况下,命令是:

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

You can realistically omit the -type f part if you're confident that you won't ever put "Test.js" in a directory name. (A safe assumption, most likely, but I included it for completeness sake)

如果您有信心不会进行“测试”,您可以实际地忽略-type f部分。在目录名中。(很可能是一个安全的假设,但出于完整性考虑,我将其包含在内)

#3


-1  

The glob expansion is actually done by your shell and that's why it works from the command line.

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

You can do mocha --recursive and point at your test directory.

您可以执行mocha——递归操作并指向您的测试目录。

#1


25  

Solution

Change your scripts so that what you pass to Mocha is protected from expansion by the shell:

更改您的脚本,以便您传递给Mocha的内容不会被shell扩展:

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

Note the single quotes around the parameter given to mocha.

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

Explanation

This issue is fixable without resorting to external tools. The root cause of your problem is that by npm uses sh as the shell that will run your script commands.

这个问题无需借助外部工具就可以解决。问题的根本原因是npm使用sh作为shell来运行脚本命令。

It is overwhelmingly the case that when a *nix process starts a shell it will start sh unless there is something telling it to do otherwise. The shell preference you set for logins does not constitute a way to "tell it otherwise". So if you have, say, zsh as your login shell, it does not entail that npm will use zsh.

绝大多数情况下,当*nix进程启动shell时,它将启动sh,除非有什么东西告诉它不这样做。您为登录设置的shell首选项并不构成一种“告诉它否则”的方法。因此,如果您有,比方说,zsh作为您的登录shell,并不需要npm使用zsh。

Those implementations of sh that do not include any extensions beyond what sh should provide do not understand the ** glob in the way you want it to. As far as I can tell, it is interpreted as *. However, Mocha interprets the paths passed to it using its a JavaScript implementation of globs. So you can work around the issue by protecting your globs from being interpreted by sh. Consider the following package.json:

那些不包含任何超出sh所应该提供的扩展的sh的实现不理解您想要的方式的** glob。据我所知,它被解释为*。但是,Mocha使用其globs的JavaScript实现来解释传递给它的路径。因此,您可以通过保护您的globs不被sh解释来解决这个问题。

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

The shell script is just so that we can check what shell is running the script. If you run it, you should see sh.

shell脚本只是为了检查哪个shell正在运行脚本。如果你运行它,你应该看到sh。

Now, given the following tree:

现在,考虑到下面这棵树:

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

With all a.js and b.js files containing it(__filename);. You get the following results:

与所有。js和b。js文件包含它(__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

#2


2  

You can inline the find command with the -name option in your scripts to replace the extended globbing syntax provided by zsh.

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

In your case, the command would be:

在你的情况下,命令是:

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

You can realistically omit the -type f part if you're confident that you won't ever put "Test.js" in a directory name. (A safe assumption, most likely, but I included it for completeness sake)

如果您有信心不会进行“测试”,您可以实际地忽略-type f部分。在目录名中。(很可能是一个安全的假设,但出于完整性考虑,我将其包含在内)

#3


-1  

The glob expansion is actually done by your shell and that's why it works from the command line.

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

You can do mocha --recursive and point at your test directory.

您可以执行mocha——递归操作并指向您的测试目录。