18

I want to be able to take a command string, for example:

some/script --option="Quoted Option" -d --another-option 'Quoted Argument'

And parse it into something that I can send to child_process.spawn:

spawn("some/script", ["--option=\"Quoted Option\"", "-d", "--another-option", "Quoted Argument"])

All of the parsing libraries I've found (e.g. minimist, etc.) do too much here by parsing it into some kind of options object, etc. I basically want the equivalent of whatever Node does to create process.argv in the first place.

This seems like a frustrating hole in the native APIs since exec takes a string, but doesn't execute as safely as spawn. Right now I'm hacking around this by using:

spawn("/bin/sh", ["-c", commandString])

However, I don't want this to be tied to UNIX so strongly (ideally it'd work on Windows too). Halp?

Michael Bleigh
  • 25,334
  • 2
  • 79
  • 85
  • It is not node.js that creates process.argv, but the shell interpreter you use. So it is system dependent. bash's interpretation will be different from that of Windows cmd. – user568109 May 06 '14 at 09:50
  • @Michael: did you find any solution. I'm facing the same problem right now. – Krasimir May 27 '14 at 22:02
  • @Krasimir nope, never found a definitive answer. I'm still using `/bin/sh` for the time being. – Michael Bleigh May 28 '14 at 05:34
  • If you're looking to split a command line sentence into args, then [string-argv](https://www.npmjs.com/package/string-argv) or [spawn-args](https://www.npmjs.com/package/spawn-args) may be helpful. – Sachin Joseph Aug 01 '20 at 18:14

2 Answers2

23

Standard Method (no library)

You don't have to parse the command string into arguments, there's an option on child_process.spawn named shell.

options.shell

If true, runs command inside of a shell.
Uses /bin/sh on UNIX, and cmd.exe on Windows.

Example:

let command = `some_script --option="Quoted Option" -d --another-option 'Quoted Argument'`

let process = child_process.spawn(command, [], { shell: true })  // use `shell` option

process.stdout.on('data', (data) => {
  console.log(data)
})

process.stderr.on('data', (data) => {
  console.log(data)
})

process.on('close', (code) => {
  console.log(code)
})
chuyik
  • 908
  • 8
  • 12
5

The minimist-string package might be just what you're looking for.

Here's some sample code that parses your sample string -

const ms = require('minimist-string')
const sampleString = 'some/script --option="Quoted Option" -d --another-option \'Quoted Argument\'';
const args = ms(sampleString);
console.dir(args)

This piece of code outputs this -

{
  _: [ 'some/script' ],
  option: 'Quoted Option',
  d: true,
  'another-option': 'Quoted Argument'
}
GPX
  • 3,506
  • 10
  • 52
  • 69