如何编写package.json脚本:传参执行prettier,无参提示无参数?
在package.json的scripts中实现带参数判断的Prettier脚本
问题情况
需要在package.json的scripts里写一个简单的bash脚本,实现两个逻辑:
- 传入参数时,执行
prettier --write [传入的路径] - 没传参数时,输出“No arguments passed”
试了很多方法都不行,最后尝试的脚本如下:
{ // ... "scripts": { // ... "format:file": "if [ \"$#\" -eq \"0\" ]; then echo \"No arguments supplied\"; else prettier --write $1; fi", } }
无参数执行时正常:
> yarn format:file yarn run v1.22.19 $ if [ "$#" -eq "0" ]; then echo "No arguments supplied"; else prettier --write $1; fi No arguments supplied ✨ Done in 0.07s.
但传参数(比如.)就报错,因为参数被直接加到命令末尾,导致语法错误:
yarn format:file . yarn run v1.22.19 $ if [ "$#" -eq "0" ]; then echo "No arguments supplied"; else prettier --write $1; fi . /bin/sh: -c: line 0: syntax error near unexpected token `.' /bin/sh: -c: line 0: `if [ "$#" -eq "0" ]; then echo "No arguments supplied"; else prettier --write $1; fi .' error Command failed with exit code 2.
问题根源
用yarn/npm执行scripts命令时,传入的参数会直接追加到脚本命令的最后,而不是成为脚本内部的位置参数($1、$#)。原来的脚本里的$#和$1是在sh启动的子shell里,这个子shell根本没拿到你传的参数,所以追加的.就变成了无效的命令后缀,触发语法错误。
解决办法
方法1:显式传递参数到子shell
用sh -c把脚本逻辑包裹起来,通过占位符_占据$0的位置,让$@能正确接收所有传入的参数:
{ "scripts": { "format:file": "sh -c 'if [ $# -eq 0 ]; then echo \"No arguments passed\"; else prettier --write \"$@\"; fi' _" } }
方法2:用短路逻辑简化脚本
如果觉得if-else太啰嗦,可以用bash的短路逻辑改写,同样配合sh -c传递参数:
{ "scripts": { "format:file": "sh -c '[ $# -eq 0 ] && echo \"No arguments passed\" || prettier --write \"$@\"' _" } }
验证效果
- 无参数执行:
yarn format:file # 输出:No arguments passed
- 传参数执行:
yarn format:file . # 正常执行 prettier --write .
内容的提问来源于stack exchange,提问作者Liran H
相关产品推荐
相关产品推荐

