npm脚本使用进程替换的命令失败

时间:2016-11-24 15:31:32

标签: node.js bash npm-scripts

在我的标准OSX终端上运行以下按预期工作:

$ diff <(ls dir1) <(ls dir2)
correct output here

但是当我尝试将其作为NPM脚本运行时,它失败了:

$ npm run diff
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `diff <(ls src) <(ls dist)'

当我将NPM脚本更改为"bash -c 'diff <(ls dir1) <(ls dir2)'"时,它首先输出所需的结果,然后抛出错误(退出状态1)。

修改:顺便说一下,那些奇怪的<()符号是process substitutions。刚刚了解了它们。

2 个答案:

答案 0 :(得分:4)

使用背景信息补充Stefan Hegny's helpful answer

来自https://docs.npmjs.com/misc/scripts

  

通过将该行作为脚本参数传递给sh来运行脚本。

     

如果脚本以0以外的代码退出,则会中止该过程。

具体来说,"scripts"文件中目标package.json条目的内容作为参数传递给sh -c,因此命令行等效于命令:

sh -c 'diff <(ls dir1) <(ls dir2)'

会以同样的方式失败,因为 当Bash被调用为sh 时,设计它无法识别process substitutions({{1} }),因为它以 POSIX兼容模式运行

流程替换不是 POSIX 的一部分:它们是 Bash特定的扩展名(在<(...)和{{}}中也受支持{1}})。

为了便于移植,您应该只在zsh条目中使用POSIX-mandated shell features - 除非您明确调用特定的shell (如在Stefan的回答中),或者直接使用,或者通过调用脚本文件,其shebang行指定要使用的shell。

不同的shell在不同的平台上充当ksh,您可以依赖的唯一功能是POSIX定义的那些。

另外请注意Stefan的答案如何在Bash命令结束时使用"scripts",以确保整个命令始终报告退出代码sh ,以确保|| exit 0不会中止处理。

答案 1 :(得分:3)

尝试

"bash -c 'diff <(ls dir1) <(ls dir2) || exit 0'"