Emre Kayan
Emre Kayan

Reputation: 43

echo ignores flag in child_process.exec()

When I type echo -n foo directly in bash, it works as expected and prints foo without any trailing new lines.

But, I've written the following code to print some text using child_process.exec() method;

var exec = require('child_process').exec;
exec("echo -n foo",
    function(error, stdout, stderr) {
        console.log(stdout);
    }
);

However, the -n flag doesn't work as expected and it prints -n foo followed by a blank line.

UPDATE: I figured out that problem occurs only on OS X, I've tried the same script on Ubuntu and it works as expected.

Upvotes: 3

Views: 2635

Answers (2)

mscdex
mscdex

Reputation: 106746

It works fine for me with at least node v0.10.30 on Linux.

This:

var exec = require('child_process').exec;
exec('echo -n foo', function(error, stdout, stderr) {
  console.dir(stdout);
});

outputs:

'foo'

However, on Windows the behavior you describe does exist, but that is because Windows' echo command is not the same as on *nix (and so it echoes exactly what came after the command).

The reason it also does not work on OS X is because (from man echo):

     Some shells may provide a builtin echo command which is similar or iden-
     tical to this utility.  Most notably, the builtin echo in sh(1) does not
     accept the -n option.

When you call exec(), node spawns /bin/sh -c "<command string>" on *nix platforms. So (as noted in the man page) /bin/sh on OS X does not support echo -n, which results in the output you're seeing. However it works from the terminal because the default shell for that user is not /bin/sh but likely /bin/bash, which does support echo -n. It also works on Linux because most systems have /bin/sh pointing to /bin/bash or some other shell that supports echo -n.

So the solution is to change the command to force the use of the echo binary instead of the built-in shell's echo:

var exec = require('child_process').exec;
exec('`which echo` -n foo', function(error, stdout, stderr) {
  console.dir(stdout);
});

or use spawn() like this:

var spawn = require('child_process').spawn,
    p = spawn('echo', ['-n', 'foo']),
    stdout = '';
p.stdout.on('data', function(d) { stdout += d; });
p.stderr.resume();
p.on('close', function() {
  console.dir(stdout);
});

or if you want to keep using exec() without changing the code, then make /bin/sh a symlink to /bin/bash.

Upvotes: 5

Brendan
Brendan

Reputation: 2945

The JavaScript console.log function appends a \n newline character to a string. If you want to print a string without a newline character, you can do it like this:

var exec = require('child_process').exec;
exec("echo -n foo",
    function(error, stdout, stderr) {
        process.stdout.write(stdout);
    }
);

Upvotes: -1

Related Questions