Meu comando `qual` pode estar errado (algumas vezes)?

17

Compilei a última versão do emacs a partir do código fonte (v24.2) porque a versão instalada na minha máquina é (bastante) antiga para mim (v21.3). Eu fiz o de sempre:

$configure --prefix=$HOME
make 
make install

Agora estou testando o emacs e percebi que ele ainda lança a versão anterior ... enquanto o meu $HOME/bincaminho deve substituir o sistema (já que é precedido por $ PATH no meu .bashrcarquivo).

Meu primeiro pensamento foi ver a whichsaída do comando. E surpresa, dá o caminho para o novo emacs. Não consigo entender onde está a discrepância aqui. Na mesma sessão, aqui estão as diferentes saídas:

$ emacs --version
GNU Emacs 21.3.1

$ `which emacs` --version
GNU Emacs 24.2.1

Não tenho pseudônimo envolvendo emacs. Em absoluto.

$ alias | grep emacs
$

Alguma idéia do que está acontecendo, por favor?

yves Baumes
fonte
o que emacs retorna?
Ulrich Dangel

Respostas:

29

As três possibilidades que me vêm à mente:

  • Existe um alias para emacs(que você verificou)
  • Existe uma função para emacs
  • O novo emacsbinário não está na hashtable PATH do seu shell.

Você pode verificar se possui uma função emacs:

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

E remova-o:

unset -f emacs

Seu shell também possui uma hashtable PATH que contém uma referência a cada binário no seu PATH. Se você adicionar um novo binário com o mesmo nome que um existente em outro lugar no seu PATH, o shell precisará ser informado atualizando a hashtable:

hash -r

Explicação adicional:

which não sabe sobre funções, pois não é um bash embutido:

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

O novo comportamento de hashtable binário é demonstrado por este 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

Embora eu não o chamasse, which catsempre retornaria o primeiro catno meu PATH, porque ele não usa a hashtable do shell.

mrb
fonte
1
Embora haja boas informações aqui, elas perdem o typecomando.
Jordanm # 6/12
Obrigado, eu tive o mesmo problema com uma versão recém-compilada do sqlite3 que me deixou maluco (que na verdade retornou o caminho certo, mas o shell não chamou o sqlite3 cli correto). hash -rcorrigiu meu problema.
mpm
12

Sim, não use qual :

  • Em alguns sistemas, é um comando externo implementado como um script csh, que pode ler uma configuração que altera o PATH.
  • Há um builtin para isso. Dois, pares: typee command. A maneira POSIX:

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

    No bash, você também pode usar type -p emacspara ver apenas o caminho de um comando externo.

No entanto, aqui, whichestá realmente certo. O Bash mantém informações sobre a localização de um comando na memória, para que ele possa executar o comando mais rapidamente na próxima vez. Você instalou um novo emacsexecutável no seu PATH, mas o bash ainda possui o local antigo em seu cache. Execute hash emacspara procurar emacsnovamente ou hash -resvaziar o cache.

Gilles 'SO- parar de ser mau'
fonte
1

Você efetuou logout e login para fazer com que seu .bashrcarquivo de login atualizado seja relido? Caso contrário, o ambiente da sua sessão atual não foi atualizado.

JRFerguson
fonte
Se fosse esse o caso, `which emacs` --versionconcordaria com emacs --version, porque whichherda seu PATH do shell atual.
mrb 6/09/12
@ MRB: Ponto bem tomado.
JRFerguson