totymedli
totymedli

Reputation: 31088

How to force npm bin -g to print only the path

Task

I want to use the path returned by npm bin -g in a script.

Problem

npm bin -g returns the path then also prints to a new line that it isn't part of PATH env variable:

/home/username/.npm-global/bin
(not in PATH env variable)

To make it even more random, sometimes it prints this upgrade notice too:

 ╭─────────────────────────────────────╮
 │                                     │
 │   Update available 5.3.0 → 5.6.0    │
 │     Run npm i -g npm to update      │
 │                                     │
 ╰─────────────────────────────────────╯

These cause an error message in my script and halts its execution.

Popup error message. Nothing happens until you OK this.

What have I tried

I tried to process only the first line of the output with npm bin -g | head -n 1 but the second line still persists. I even tried npm bin -g > /dev/null but that made only the path go away, I still have the notice. What is going on?

Upvotes: 5

Views: 132

Answers (1)

totymedli
totymedli

Reputation: 31088

tl;dr

Use npm bin -g 2> /dev/null

Explanation

The notice is printed to stderr. You need to redirect that to /dev/null with 2>.

If you check out the implementation of the npm bin command:

function bin (args, silent, cb) {
  if (typeof cb !== 'function') {
    cb = silent
    silent = false
  }
  var b = npm.bin
  var PATH = osenv.path()

  if (!silent) output(b)
  process.nextTick(cb.bind(this, null, b))

  if (npm.config.get('global') && PATH.indexOf(b) === -1) {
    npm.config.get('logstream').write('(not in PATH env variable)\n')
  }
}

You can see that in the end it checks if the path is in the PATH and if not, then prints the message to logstream. logstream comes from npm.config. If you check the defaults for that, you can see in this line, that it uses stderr:

logstream: process.stderr,

That is the reason why getting the first line only didn't worked, there were no second line. Also, > /dev/null redirected stdout, so you left only with the message from stderr. You can redirect stderr with 2>.

Upvotes: 4

Related Questions