Node: child_process.spawn fails on Windows given a space in both the command and an argument

Created on 22 Jun 2016  Â·  19Comments  Â·  Source: nodejs/node

  • Version: 4.4.4, 4.4.7, 5.10.1, 6.2.2
  • Platform: Windows 7, 64-bit
  • Subsystem: child_process

Reproduction of the error: https://gist.github.com/smrq/f028b22bc748af9e68a7

On Windows, child_process.spawn handles the command incorrectly when both it and one of its arguments contains a space. So, this works fine:

var spawn = require('child_process').spawn;

spawn('nospaces.cmd', ['arg with spaces']);
spawn('command with spaces.cmd', ['nospaces']);

But this yields 'command' is not recognized as an internal or external command, operable program or batch file.:

spawn('command with spaces.cmd', ['arg with spaces']);

(This is node-v0.x-archive #25895, still extant in higher Node.js versions.)

child_process windows

Most helpful comment

Unfortunately I haven't been able to find a fix that would not also break a lot of other use cases. But there is luckily easy work around for this issue - you need to quote script filename and add shell:true to options:

spawn('"with spaces.cmd"', ['arg with spaces'], { shell: true });

All 19 comments

/cc @nodejs/platform-windows

I can reproduce, working on a fix.

I've had success using https://github.com/nodejs/node-v0.x-archive/issues/25895#issuecomment-180402332 from the linked issue as a work around.

Is this an issue with exec() too?

They are related, exec internally calls spawn.

The problem is in how shell commands are executed under Windows. I have a fix almost ready, I'll publish it probably tomorrow.

Does this _not_ happen on v4?

exec internally calls spawn.

I get that. I was asking if exec() was affected as well, since it does some manipulation before passing to spawn.

@mcollina Problem exists on v4.4.4 as well.

@s100 can you check on v4.4.7

LTS is affected for sure thats what I'm using.

Im my case we are only using spawn but given its at the point of exec I assume its affected too.

@TheAlphaNerd still present on v4.4.7. Any others?

Unfortunately I haven't been able to find a fix that would not also break a lot of other use cases. But there is luckily easy work around for this issue - you need to quote script filename and add shell:true to options:

spawn('"with spaces.cmd"', ['arg with spaces'], { shell: true });

Thats pretty much what my fixed boiled down to, quoting the cmd

Kindest Regards,

Dean

On 30 Jun 2016, at 17:59, Bartosz Sosnowski [email protected] wrote:

Unfortunately I haven't been able to find a fix that would not also break a lot of other use cases. But there is luckily easy work around for this issue - you need to quote script filename and add shell:true to options:

spawn('"with spaces.cmd"', ['arg with spaces'], { shell: true });

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

I don't think we can do anything more with this so I'm closing the issue. You can always reopen it if you feel so.

@bzoz Do you mean that the issue is fixed now?

@s100 sorry, I didn't make myself clear and provide summary. My bad.

The thing is, there is no way to fix this. When calling shell scripts under Windows, you need to add {shell: true} to make sure things work ok (doc link). Shell scripts are not executable files under Windows, so they need special treatment. Also, Windows takes all arguments as single strings, not as array like Linux does.

When the script filename has space in it, it needs to be quoted. We cannot do this automatically - spawn is used by exec, for which users pass command and arguments as a single string. If we would add quotes we would break usages like in test-exec.js:93.

FWIW I've opened a PR to add a example to the documentation: https://github.com/nodejs/node/pull/8035

When the script filename has space in it, it needs to be quoted. We cannot do this automatically - spawn is used by exec, for which users pass command and arguments as a single string. If we would add quotes we would break usages like in test-exec.js:93.

How does that follow? exec on Windows is implemented in terms of spawn(…, { windowsVerbatimArguments: true }), but shouldn’t spawn without windowsVerbatimArguments quote and escape the command and arguments?

Currently there’s no way to make a command like childProcess.spawn('npm', ['install', 'eslint@>=4.1.1']) work in a cross-platform way. It works on Unix, but as written it fails with ENOENT on Windows, and with { shell: true } the shell mangles the command and redirects the output of npm install eslint@ to a file named =4.1.1. The latter failure also happens without { shell: true } if the 'npm' is changed to 'npm.cmd'.

For anyone who comes here just looking for a workaround like I did, the cross-spawn package seems to implement the right API.

// DON'T WRITE THE http://
var options = {
host: 'http://yoururl.com',
path: '/path/to/resource'
};

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ctavan picture ctavan  Â·  87Comments

jonathanong picture jonathanong  Â·  93Comments

VanCoding picture VanCoding  Â·  204Comments

substack picture substack  Â·  878Comments

speakeasypuncture picture speakeasypuncture  Â·  152Comments