Ma commande `quelle` peut être erronée (parfois)?

17

J'ai compilé la dernière version d'emacs à partir du code source (v24.2) car la version installée sur ma machine est (assez) ancienne pour moi (v21.3). J'ai fait comme d'habitude:

$configure --prefix=$HOME
make 
make install

Maintenant, je teste emacs et j'ai réalisé qu'il lance toujours la version précédente ... alors que mon $HOME/binchemin est censé remplacer celui du système (car il est ajouté à $ PATH dans mon .bashrcfichier).

Ma première pensée a été de voir la whichsortie de la commande. Et surprise, elle ouvre la voie aux nouveaux emacs. Je ne peux pas comprendre où est la différence ici. Dans la même session, voici les différentes sorties:

$ emacs --version
GNU Emacs 21.3.1

$ `which emacs` --version
GNU Emacs 24.2.1

Je n'ai pas d'alias impliquant emacs. Du tout.

$ alias | grep emacs
$

Une idée de ce qui se passe s'il vous plaît?

yves Baumes
la source
qu'est-ce que les emacs retournent?
Ulrich Dangel

Réponses:

29

Les trois possibilités qui me viennent à l'esprit:

  • Il existe un alias emacs(que vous avez vérifié)
  • Une fonction existe pour emacs
  • Le nouveau emacsbinaire n'est pas dans la table de hachage PATH de votre shell.

Vous pouvez vérifier si vous avez une fonction emacs:

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

Et retirez-le:

unset -f emacs

Votre shell a également une table de hachage PATH qui contient une référence à chaque binaire de votre PATH. Si vous ajoutez un nouveau binaire avec le même nom qu'un existant ailleurs dans votre PATH, le shell doit être informé en mettant à jour la table de hachage:

hash -r

Explication supplémentaire:

which ne connaît pas les fonctions, car ce n'est pas une commande bash:

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

Un nouveau comportement de table de hachage binaire est démontré par ce 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

Bien que je ne l'appelle pas, which catje retournerais toujours le premier catdans mon PATH, car il n'utilise pas la table de hachage du shell.

mrb
la source
1
Bien qu'il existe de bonnes informations ici, il manque la typecommande.
jordanm
Merci, j'ai eu le même problème avec une version fraîchement compilée de sqlite3 qui m'a rendu fou (qui a en fait renvoyé le bon chemin, mais le shell n'a pas appelé le bon sqlite3 cli). hash -ra résolu mon problème.
mpm
12

Oui, n'utilisez pas lequel :

  • Sur certains systèmes, il s'agit d'une commande externe implémentée en tant que script csh, qui peut lire une configuration qui modifie le PATH.
  • Il y a une fonction intégrée pour cela. Deux, même: typeet command. La manière POSIX:

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

    En bash, vous pouvez également utiliser type -p emacspour voir uniquement le chemin d'une commande externe.

Cependant, ici, whichc'est vraiment vrai. Bash conserve des informations sur l'emplacement d'une commande en mémoire, afin de pouvoir exécuter la commande plus rapidement la prochaine fois. Vous avez installé un nouvel emacsexécutable sur votre PATH, mais bash a toujours l'ancien emplacement dans son cache. Exécutez hash emacspour rechercher à emacsnouveau ou hash -rpour vider le cache.

Gilles 'SO- arrête d'être méchant'
la source
1

Vous êtes-vous déconnecté et connecté pour que votre .bashrcfichier de connexion mis à jour soit relu? Sinon, l'environnement de votre session actuelle n'a pas été mis à jour.

JRFerguson
la source
Si tel était le cas, `which emacs` --versionserait d'accord avec emacs --version, car whichhérite son PATH du shell actuel.
mrb
@mrb: Point bien pris.
JRFerguson