¿Mi comando `which` puede estar equivocado (a veces)?

17

He compilado la última versión de emacs del código fuente (v24.2) porque la versión instalada en mi máquina es (bastante) antigua para mí (v21.3). He hecho lo usual:

$configure --prefix=$HOME
make 
make install

Ahora estoy probando emacs y me di cuenta de que todavía lanza la versión anterior ... mientras $HOME/binse supone que mi ruta anulará la del sistema (ya que se antepone a $ PATH en mi .bashrcarchivo).

Mi primer pensamiento fue ver la whichsalida del comando. Y sorpresa, da el camino a los nuevos emacs. No puedo entender dónde está la discrepancia aquí. En la misma sesión, aquí están las diferentes salidas:

$ emacs --version
GNU Emacs 21.3.1

$ `which emacs` --version
GNU Emacs 24.2.1

No tengo un alias relacionado con emacs. En absoluto.

$ alias | grep emacs
$

¿Alguna idea de lo que está pasando por favor?

yves Baumes
fuente
¿Qué devuelve qué emacs?
Ulrich Dangel

Respuestas:

29

Las tres posibilidades que me vienen a la mente:

  • Existe un alias para emacs(que has marcado)
  • Existe una función para emacs
  • El nuevo emacsbinario no está en la tabla hash PATH de su shell.

Puede verificar si tiene una función emacs:

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

Y eliminarlo:

unset -f emacs

Su shell también tiene una tabla hash PATH que contiene una referencia a cada binario en su PATH. Si agrega un nuevo binario con el mismo nombre que uno existente en otra parte de su RUTA, se debe informar al shell actualizando la tabla hash:

hash -r

Explicación adicional:

which no conoce las funciones, ya que no es un bash incorporado:

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

Este nuevo script demuestra un nuevo comportamiento de tabla hash binaria.

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

Aunque no lo llamé, which catsiempre devolvería el primero caten mi RUTA, porque no usa la tabla hash del shell.

mrb
fuente
1
Si bien hay buena información aquí, se pierde el typecomando.
jordanm
Gracias, tuve el mismo problema con una versión recién compilada de sqlite3 que me volvió loco (que en realidad devolvió el camino correcto, pero el shell no llamó al cli sqlite3 correcto). hash -rsolucionó mi problema.
mpm
12

Sí, no uses cuál :

  • En algunos sistemas, es un comando externo implementado como un script csh, que puede leer una configuración que cambia el PATH.
  • Hay algo para eso. Dos, incluso: typey command. La forma POSIX:

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

    En bash, también puede usar type -p emacspara ver solo la ruta de un comando externo.

Sin embargo, aquí, en whichrealidad tiene razón. Bash mantiene información sobre la ubicación de un comando en la memoria, para que pueda ejecutar el comando más rápido la próxima vez. Has instalado un nuevo emacsejecutable en tu PATH, pero bash todavía tiene la ubicación anterior en su caché. Ejecute hash emacspara buscar emacsnuevamente o hash -rpara vaciar el caché.

Gilles 'SO- deja de ser malvado'
fuente
1

¿Salió e inició sesión para .bashrcvolver a leer su archivo de inicio de sesión actualizado ? De lo contrario, el entorno de su sesión actual no se ha actualizado.

JRFerguson
fuente
Si ese fuera el caso, `which emacs` --versionestaría de acuerdo con emacs --version, porque whichhereda su RUTA del shell actual.
mrb
@mrb: Punto bien tomado.
JRFerguson