12

I have installed node.js at custom location and added the location to the $PATH in .profile file.

$ node --version
v0.6.2
$ which node
$ echo $PATH
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:~/Unix/homebrew/bin
$ cat ~/.profile
export  PATH="$PATH:~/Unix/homebrew/bin"

Node.js itself runs well. The problem is it is not listed by which command. So I can't install npm now. Because npm install cannot find the location of node.js. How can I make the node binary discovered by which?

Eonil
  • 4,657

2 Answers2

19

That line in your .profile should be one of

export  PATH="$PATH:$HOME/Unix/homebrew/bin"
PATH="$PATH:$HOME/Unix/homebrew/bin"
PATH=$PATH:$HOME/Unix/homebrew/bin
PATH=$PATH:~/Unix/homebrew/bin

The ~ character is only expanded to your home directory when it's the first character of a word and it's unquoted. In what you wrote, the ~ is between double quotes and therefore not expanded. Even if you wrote export "PATH=$PATH:"~/Unix/homebrew/bin, the ~ would not be expanded because it is not at the beginning of a shell word.

There is a special dispensation, which is intended to write values for PATH and similar variables. If ~ is just after the equal sign that marks an assignment, or if ~ is just after a : in the right-hand side of an assignment, then it's expanded. Only plain assignments have this dispensation, export PATH=… does not count (it's a call to the export builtin, which happens to have an argument that contains a = character).

Here, you do not need to export PATH because it's already exported. You don't need to call export when you change the value of a variable (except in old Bourne shells that you won't find on OSX or Linux). Also, in an assignment (again, export does not count), you do not need double quotes around the right-hand side, so PATH=$PATH:~/Unix/homebrew/bin is safe even if $PATH contains spaces.

11

This is happening because ~ has not been expanded. Your shell knows how to deal with this, but which does not (nor would most other programs). Instead, do:

export "PATH+=:$HOME/Unix/homebrew/bin"

Alternatively, stop using which, and use the (almost always superior) type -p.

Here is a demonstration of the issue:

$ echo "$PATH"
/usr/local/bin:/usr/bin:/bin
$ export "PATH+=:~/git/yturl"
$ yturl
Usage: yturl id [itag ...]
$ which yturl
$ type -p yturl
/home/chris/git/yturl/yturl
$ export "PATH=/usr/local/bin:/usr/bin:/bin:$HOME/git/yturl"
$ which yturl
/home/chris/git/yturl/yturl

Bear in mind that some other programs that look at $PATH may not understand the meaning of ~ either, and take it as part of a relative path. It's more portable to use $HOME.

jw013
  • 51,212
Chris Down
  • 125,559
  • 25
  • 270
  • 266
  • 1
    While the proposed solution does work, the explanation is wrong. which is not at fault here; the ~ should have been expanded in the definition of PATH. There's an oddity in bash that it expands the ~ anyway in PATH, so two wrongs make a right, kind of. – Gilles 'SO- stop being evil' Nov 29 '11 at 21:57
  • @Gilles How does that differ from what I said? – Chris Down Nov 29 '11 at 23:09
  • The fact that this works at all with the quoted ~ is a bash oddity. Having that literal ~ in $PATH is likely to cause trouble down the line because there are programs that do their own splitting of $PATH and they don't treat ~ specially. – Gilles 'SO- stop being evil' Nov 29 '11 at 23:14
  • @Gilles ...and how does that differ from what I said in my final paragraph? – Chris Down Nov 29 '11 at 23:37
  • 1
    While it's technically true that “some other program … may not understand the meaning of ~”, your sentence is misleading. In the context of $PATH, this is every program other than bash. – Gilles 'SO- stop being evil' Nov 30 '11 at 01:07
  • Where as type -p may be superior, which is far easier to remember for a command that you type once every few months. – icc97 Jul 30 '19 at 10:16