1

I basically took this bash recipe to run different commands based on whether a package.json script is called with or without a parameter...

"scripts": {
    "paramtest": "if [ -z $1 ]; then echo \"var is unset\"; else echo \"var is set to {$1}\"; fi",
    ...

Calling without a parameter works as expected:

$>yarn paramtest
var is unset
$>npm run paramtest
var is unset
$>

Calling with a parameter gives me an error:

$>yarn run paramtest foo
/bin/sh: 1: Syntax error: word unexpected
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
$>npm run paramtest -- foo

> photocmd@0.0.7 paramtest /depot/own/photocmd

sh: 1: Syntax error: word unexpected
...

What's wrong?

tk421
  • 5,775
  • 6
  • 23
  • 34
Frank N
  • 9,625
  • 4
  • 80
  • 110

1 Answers1

2

According to this answer and this comment, yarn run only supports passing arguments to the end of a script, and not to the middle. This behaviour is analogous to npm run.

To circumvent this limitation you'll need to place your current conditional logic in the body of a bash function. For instance:

"scripts": {
  "paramtest": "func () { if [ -z \"$1\" ]; then echo \"var is unset\"; else echo \"var is set to ${1}\"; fi ;}; func",
...

Now when you pass an argument to the script via your CLI it gets:

  1. Added to the end of the paramtest script, i.e. after the func invocation.
  2. Subsequently passed as an argument to the func function itself.
  3. In the body of the func function the first parameter is referenced using $1 in the test, and ${1} in the echo string.

Note: The $1 in the test is wrapped in json escaped double quotes, i.e. \"$1\"

Running the script:

When passing an argument to your script via your CLI it would be safer to also include -- between the script name, (i.e. paramtest), and the argument (foo). For instance:

yarn run paramtest -- foo
                   ^^

Because if your argument begins with a hyphen (as shown in the following command) it will be interpreted as an option:

yarn run paramtest -foo
                   ^

and your script will print:

var is unset

However, adding the -- as shown in the following example;

yarn run paramtest -- -foo
                   ^^ ^

correctly prints:

var is set to -foo

RobC
  • 22,977
  • 20
  • 73
  • 80
  • The same solution is also applicable to your [other question](https://stackoverflow.com/questions/51401352/if-else-on-arguments-in-npm-run-script). – RobC Oct 10 '18 at 11:18