24

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?

jasonwryan
  • 73,126

3 Answers3

37

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.

mrb
  • 10,288
  • 1
    While there is good information here, it misses out on the type command. – jordanm Sep 06 '12 at 22:06
  • Thanks, I had the same issue with a freshly compiled version of sqlite3 which made me nut (which actually did return the right path, but the shell didn't call the right sqlite3 cli). hash -r did fix my issue. – mpm Sep 29 '18 at 12:11
15

Yes, don't use which:

  • On some systems, it's an external command implemented as a csh script, which may read a configuration that changes the PATH.
  • There's a builtin for that. Two, even: type and command. The POSIX way:

    command -v emacs       # machine-readable format
    type emacs             # human-only format
    

    In bash, you can also use type -p emacs to see just the path of an external command.

However, here, which is actually right. Bash keeps information about the location of a command in memory, so that it can execute the command faster the next time. You've installed a new emacs executable on your PATH, but bash still has the old location in its cache. Run hash emacs to look up emacs again, or hash -r to empty the cache.

1

Did you logout and login to cause your updated .bashrc login file to be re-read? If not, your current session's environment hasn't been updated.

JRFerguson
  • 14,740