Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arguments in quotes not handled correctly #354

Closed
agirorn opened this issue Jul 26, 2019 · 3 comments
Closed

Arguments in quotes not handled correctly #354

agirorn opened this issue Jul 26, 2019 · 3 comments

Comments

@agirorn
Copy link

agirorn commented Jul 26, 2019

The command execa.command does not handle arguments in quotes correctly. It splits all strings by space and ignores arguments in quotes.

What happend
To test this I have this script

#!/usr/bin/env node
console.log(process.argv);

That I run like this and it splits argument 2 ('arg 2') into 2 arguments.

> command("./test.js arg1 'arg 2'").then(console.log)
Promise { <pending> }
> {
  command: "./test.js arg1 'arg 2'",
  exitCode: 0,
  exitCodeName: 'SUCCESS',
  stdout: '[\n' +
    "  '/home/agirorn/.nvm/versions/node/v12.7.0/bin/node',\n" +
    "  '/home/agirorn/code/pontus/docs/test.js',\n" +
    "  'arg1',\n" +
    `  "'arg",\n` +
    `  "2'"\n` +
    ']',
  stderr: '',
  all: '[\n' +
    "  '/home/agirorn/.nvm/versions/node/v12.7.0/bin/node',\n" +
    "  '/home/agirorn/code/pontus/docs/test.js',\n" +
    "  'arg1',\n" +
    `  "'arg",\n` +
    `  "2'"\n` +
    ']',
  failed: false,
  timedOut: false,
  isCanceled: false,
  killed: false
}

What I expected
I expected argument 2 ('arg 2') not to be split into 2 arguments.

> command("./test.js arg1 'arg 2'").then(console.log)
Promise { <pending> }
> {
  command: "./test.js arg1 'arg 2'",
  exitCode: 0,
  exitCodeName: 'SUCCESS',
  stdout: '[\n' +
    "  '/home/agirorn/.nvm/versions/node/v12.7.0/bin/node',\n" +
    "  '/home/agirorn/code/pontus/docs/test.js',\n" +
    "  'arg1',\n" +
    `  "'arg 2'"\n` +
    ']',
  stderr: '',
  all: '[\n' +
    "  '/home/agirorn/.nvm/versions/node/v12.7.0/bin/node',\n" +
    "  '/home/agirorn/code/pontus/docs/test.js',\n" +
    "  'arg1',\n" +
    `  "'arg 2'"\n` +
    ']',
  failed: false,
  timedOut: false,
  isCanceled: false,
  killed: false
}

Maybe something similar to shell-parsercould be used instead of the "SPACES_REGEXP" string split

@ehmicky
Copy link
Collaborator

ehmicky commented Jul 26, 2019

Quoting is shell-specific. shell-parser is for Unix only, Windows cmd.exe quoting is very different. We don't want to promote non-cross-platform code.

Instead you have three options:

  1. Escape the significant spaces with backslashes: execa.command('./test.js arg1 arg\\ 2')
  2. use execa() instead of execa.command(): execa('./test.js', ['arg1', 'arg 2'])
  3. use the shell option in order to let your current shell handle it. That option has many drawbacks so I would not recommend it though.

@ehmicky ehmicky closed this as completed Jul 26, 2019
@agirorn
Copy link
Author

agirorn commented Jul 26, 2019

Thanks for the fast response to this issue.

@retueZe
Copy link

retueZe commented Jul 8, 2023

We don't want to promote non-cross-platform code.

  1. Escape the significant spaces with backslashes: execa.command('./test.js arg1 arg\ 2')

You contradict yourself. execa.command('./test.js arg1 arg\\ 2') does not work in cmd.exe. The passed command to the terminal is going to be ./test.js arg1 arg\ 2. First off, not every Windows NodeJS user makes *.js files executable in the *nix-like way. Better to use node ./test.js arg1 arg\ 2. Okay, but this code is not cross-platform either. Let's create a 'test.js' file with the following code:

console.log(process.argv.slice(2))

Then execute the node ./test.js arg1 arg\ 2 command. The output is going to be:

[ 'arg1', 'arg\\', '2' ]

Yes, it does work in BASH, but not in Batch. The only case where is not desirable to use the 2nd way is when you use $, and especially $$, where the 1st option is the only one available, and it just doesn't work at all default shells.

What did you mean by that:

Quoting is shell-specific.

BASH has double-quotes, Batch has double-quotes, PowerShell has double-quotes. The only difference is escaping and variable substitution. The first one is solved by JS' escaping. The second one solved by either using interpolated strings ($, for example), or passing arguments by array. But as i said, you get completely stuck by using the $ (the most laconic and pretty option so far).

So, is double-quoting really some kind of "non-cross-platform code"? Why can't this feature just be implemented? I really see no way to make some bad code out of double-quoting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants