首页 > 解决方案 > 如果在“npm shell”中工作,为什么不能在 npm package.json 脚本中使用**(用于递归通配)?

问题描述

所以我在这里有一个示例项目,其结构如下:

wc-npm-test ❯ tree

├── dir0
│   ├── dir0-1
│   │   └── jsfile.js
│   └── jsfile.js
├── dir1
│   ├── dir1-1
│   │   └── jsfile.js
│   └── jsfile.js
├── jsfile.js
└── package.json

4 directories, 6 files

每个jsfile.js包含 3 行:

console.log("line");
console.log("line");
console.log("line");

在 package.json 我有两个脚本:

  "scripts": {
    "wc": "wc -l **/*.js",
    "shell": "echo $SHELL"
  },

现在,当我使用此命令直接将其键入终端时,我得到如下结果:

wc-npm-test ❯ wc -l **/*.js    
       3 dir0/dir0-1/jsfile.js
       3 dir0/jsfile.js
       3 dir1/dir1-1/jsfile.js
       3 dir1/jsfile.js
       3 jsfile.js
      15 total

但是当我将它用作 npm 脚本时,它给了我这个结果:

wc-npm-test ❯ npm run wc       

> wc-npm-test@1.0.0 wc
> wc -l **/*.js

       3 dir0/jsfile.js
       3 dir1/jsfile.js
       6 total

因此,当它由 npm 执行时,它只计算dir0dir1目录中的文件,将 **/*.js 解释为所有 1 个深度文件夹中的所有 .js 文件。但是当直接在终端中输入时,它会像往常一样被解释 - 从那时起的所有文件夹和文件。

谁能向我解释为什么会这样?

我的默认终端是 zsh。Npm 使用相同的 shell,基于这些脚本:

wc-npm-test ❯ npm run shell

> wc-npm-test@1.0.0 shell
> echo $SHELL

/bin/zsh

wc-npm-test ❯ echo $SHELL
/bin/zsh

npm --version 7.5.2

节点--版本 v14.15.0

zsh --version zsh 5.8 (x86_64-apple-darwin19.3.0)

标签: npmshzshglobnpm-scripts

解决方案


SHELL环境变量是用户首选的交互式shell。它通常不用于脚本,也不应该使用,因为这是用户偏好,并且没有特别的理由说明用户首选的 shell 会实现脚本的语言。

在脚本的上下文中,在类 Unix 环境中,“shell”具体表示sh,也称为“POSIX shell”或 Bourne 样式的 shell。POSIX sh 基于历史悠久的 Bourne shell,但有一些细微差别。Bash(几乎)与 POSIX sh 兼容。Zsh 与 POSIX sh 大体相似,但有一些不同之处。

**/递归遍历目录的通配符是 POSIX sh 的 zsh 扩展。此扩展也存在于 bash 和 ksh 中,但默认情况下未启用。它不存在于其他流行的 sh 实现中,例如 dash。

在 sh 脚本中,要递归遍历目录,请使用该find命令。


推荐阅读