将其包装在 shell 函数中应该可以解决问题:
"test": "f() { if [ $# -eq 0 ]; then mocha './test/**/*.test.js'; else mocha -- \"$@\"; fi; }; f"
请注意,我稍微更改了 if 条件和 else 分支,以便您可以在必要时指定多个文件参数。
更简洁的方法:
"test": "f() { mocha -- \"${@:-./test/**/*.test.js}\"; }; f"
以这种方式使用 shell 函数可能看起来很熟悉,因为相同的技术经常用于git 别名 https://stackoverflow.com/questions/3321492/git-alias-with-positional-parameters.
详细说明
我们用这个脚本来演示一下:
"scripts": {
"myscript": "if [ \"$1\" = one ]; then printf %s\\\\n \"$@\"; else echo false; fi"
}
这里如果第一个参数是“one”,我们打印所有参数,否则我们打印“false”。我们当然假设npm run-script
使用类似 sh 的 shell,而不是 Windows 的 cmd.exe。
我在其中看不到任何内容npm 文档 https://docs.npmjs.com/cli/run-script特别详细地how参数被传递给脚本,所以让我们看一下源代码(撰写本文时为 npm v6.14.7)。脚本似乎与它的参数结合在一起here https://github.com/npm/cli/blob/v6.14.7/lib/run-script.js#L169然后被执行here https://github.com/npm/npm-lifecycle/blob/v3.1.5/index.js#L311。本质上,npm run myscript -- one two three
becomes
sh -c 'if [ "$1" = one ]; then printf %s\\n "$@"; else echo false; fi "one" "two" "three"'
我们的论点one two three
只是用引号转义并连接到脚本命令。就 shell 语法而言,这意味着它们最终会作为参数fi
. sh
当然拒绝这一点,因为fi
只是一个内置的结束if
并且不接受任何争论。
我们的目标更像是
sh -c 'if [ "$1" = one ]; then printf %s\\n "$@"; else echo false; fi' sh "one" "two" "three"
Here one
, two
, and three
是 sh 本身的参数,因此成为参数变量$1
, $2
, and $3
在给定的脚本中。 npm 不允许我们直接执行此操作,但我们可以通过将脚本包装在 shell 函数中来完成相同的操作:
"scripts": {
"myscript": "f() { if [ \"$1\" = one ]; then printf %s\\\\n \"$@\"; else echo false; fi; }; f"
}
这里的脚本以函数的调用结束,因此 npm 最终将连接此调用的参数,最终将函数调用为f "one" "two" "three"
:
sh -c 'f() { if [ "$1" = one ]; then printf %s\\n "$@"; else echo false; fi; }; f "one" "two" "three"'