Bash – Troubleshooting ‘which’ Command Issues

bashemacspathwhich

I've compiled the last emacs version from the source code (v24.2) because the version installed on my machine is (quite) old for me (v21.3). I've done the usual:

$configure --prefix=$HOME
make 
make install

Now I am testing emacs and realized that it still launches the previous version … while my $HOME/bin path is supposed to override the system one (since it is prepended to $PATH in my .bashrc file).

My first thought was to see the which command output. And surprise, it gives the path to the new emacs. I can't understand where is the discrepancy here. In the same session here is the different outputs:

$ emacs --version
GNU Emacs 21.3.1

$ `which emacs` --version
GNU Emacs 24.2.1

I have no alias involving emacs. At all.

$ alias | grep emacs
$

Any idea what is going on please?

Best Answer

The three possibilities that come to mind for me:

  • An alias exists for emacs (which you've checked)
  • A function exists for emacs
  • The new emacs binary is not in your shell's PATH hashtable.

You can check if you have a function emacs:

bash-3.2$ declare -F | fgrep emacs
declare -f emacs

And remove it:

unset -f emacs

Your shell also has a PATH hashtable which contains a reference to each binary in your PATH. If you add a new binary with the same name as an existing one elsewhere in your PATH, the shell needs to be informed by updating the hashtable:

hash -r

Additional explanation:

which doesn't know about functions, as it is not a bash builtin:

bash-3.2$ emacs() { echo 'no emacs for you'; }
bash-3.2$ emacs
no emacs for you
bash-3.2$ which emacs
/usr/bin/emacs
bash-3.2$ `which emacs` --version | head -1
GNU Emacs 22.1.1

New binary hashtable behaviour is demonstrated by this script.

bash-3.2$ PATH=$HOME/bin:$PATH
bash-3.2$ cd $HOME/bin

bash-3.2$ cat nofile
cat: nofile: No such file or directory
bash-3.2$ echo echo hi > cat
bash-3.2$ chmod +x cat
bash-3.2$ cat nofile
cat: nofile: No such file or directory

bash-3.2$ hash -r
bash-3.2$ cat nofile
hi
bash-3.2$ rm cat
bash-3.2$ cat nofile
bash: /Users/mrb/bin/cat: No such file or directory

bash-3.2$ hash -r
bash-3.2$ cat nofile
cat: nofile: No such file or directory

Although I didn't call it, which cat would always return the first cat in my PATH, because it doesn't use the shell's hashtable.

Related Question