¿Cómo usar `which` en un comando con alias?

76

Como la mayoría de los usuarios, tengo un conjunto de alias configurados para dar un conjunto predeterminado de marcas para los programas de uso frecuente. Por ejemplo,

alias vim='vim -X'
alias grep='grep -E'
alias ls='ls -G'

El problema es que si quiero usar whichpara ver de dónde proviene mi vim/ grep/ ls/ etc., el alias se interpone en el camino:

$ which vim
vim: aliased to vim -X

Esta es una salida útil, pero no es lo que estoy buscando en este caso; Sé que vimtiene un alias, vim -Xpero quiero saber de dónde viene eso vim .

A menos que temporalmente no defina el alias solo para poder usarlo which, ¿hay una manera fácil de which'desenvolver' el alias y ejecutarlo?

Editar: Parece que whiches un shell integrado con diferentes comportamientos en diferentes shells. En Bash, la sugerencia de SiegeX de la --skip-aliasbandera funciona; Sin embargo, estoy en Zsh. ¿Existe algo similar allí?

Adrian Petrescu
fuente
en zsh, si quieres saber de dónde vimviene esowhere vim
usarías

Respuestas:

105

whichen realidad es una mala manera de hacer cosas como esta, ya que hace suposiciones sobre su entorno $SHELLy los archivos de inicio (piensa) que utiliza shell; no solo a veces adivina mal, sino que generalmente no se puede decir que se comporte de manera diferente. ( whichen mi Ubuntu 10.10 no entiende --skip-aliascomo lo menciona @SiegeX, por ejemplo). typeutiliza el entorno de shell actual en lugar de hurgar en sus archivos de configuración, y se le puede decir que ignore partes de ese entorno, por lo que le muestra lo que realmente suceda en lugar de lo que sucedería en una reconstrucción de su shell predeterminado.

En este caso, type -Pomitirá cualquier alias o función:

$ type -P vim
/usr/bin/vim

También puede pedirle que despegue todas las capas, una a la vez, y que le muestre qué encontraría:

$ type -a vim
vim is aliased to `vim -X'
vim is /usr/bin/vim

(Ampliando esto de los comentarios :)

El problema whiches que generalmente es un programa externo en lugar de un shell incorporado, lo que significa que no puede ver sus alias o funciones y tiene que intentar reconstruirlos a partir de los archivos de inicio / configuración del shell. (Si se trata de un shell incorporado, como está zshpero aparentemente no bash, es más probable que use el entorno del shell y haga lo correcto).

typees un comando compatible con POSIX que debe comportarse como si fuera un elemento incorporado (es decir, debe usar el entorno del shell desde el que se invoca, incluidas las funciones y los alias locales), por lo que generalmente es un elemento integrado.

Por lo general, no se encuentra en csh/ tcsh, aunque en la mayoría de las versiones modernas whiches un shell incorporado y hace lo correcto; a veces el incorporado es en su whatlugar, y a veces no hay una buena manera de ver el entorno actual del shell desde csh/ tcshen absoluto.

geekosaur
fuente
66
¡Gracias! Esto es algo muy útil para agregar a mi bolsa de trucos. Me gusta especialmente que type -aparece devolver todas las instancias en tu $PATH, no solo la primera. Creo que voy a alias whicha type:)
Adrian Petrescu
2
@ geekosaur: gracias. Si typees parte del estándar POSIX, ese es el camino a seguir. Para responder a mi pregunta, escriba works en zsh también (en Debian). ¿Por qué no se eliminan las distribuciones whaty whichsi no están estandarizadas y no tienen funcionalidad adicional?
Faheem Mitha
1
No, ni remotamente.
geekosaur
1
@Faheem: re documentación, comenzaría con info bash 'Bash builtins'Linux, aunque también puede obtenerlo en el zshmanual de referencia. Más oficialmente, pubs.opengroup.org/onlinepubs/009695399/utilities/type.html (lo cual noto que en realidad no especifica -Po -a, o incluso -pcuál era la forma original -P, pero sí requiere que use el entorno de shell actual).
geekosaur
2
type -pse comporta de manera diferente entre zsh y bash. type -Pno existe en zsh en absoluto.
kojiro
15

En bash:

type -P vim

En zsh:

type -p vim

En ambos:

/usr/bin/which vim

O:

( unalias vim; type vim )
Mikel
fuente
2
El último es genial. Podemos tener un alias para hacer esto. :)
balki
En bash on redhat tengo que usar el tipo -P, y no cuál, si quiero la respuesta correcta. No se trata de alias o funciones.
Dr. Eval, ¿qué "cuál"? ¿Qué sombrero rojo?
Mikel
@Mikel RH7.4. GNU que v2.20.
4

En zsh whichhay una función incorporada, ya que este comando informa:

$ whence -w which
which: builtin

Para ejecutar el comando externo (en cualquier shell) which, use la ruta completa :

$ /bin/which ls; echo $?
/bin/ls
0

así lsse encontró el comando (un valor de salida de 0) y se encuentra en /bin/ls.

Adentro zsh; Una forma (además de la anterior) para buscar comandos externos es:

$ whence -p ls
/bin/ls

Sin embargo, eso no resolverá los alias anidados como:

$ alias dire='ls -l'

El comando informará que no direse encontró ningún comando.

$ whence -p dire; echo $?
1

Para resolver alias anidados (manualmente) ver Resolve nested aliases to their source commands

HalosGhost
fuente
2

La mía definida como tal

alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
Meitham
fuente
1

Intenta lo siguiente:

which --skip-alias vim
SiegeX
fuente
1
¡Interesante! Esto funciona en Bash, pero no en Zsh (realmente no pensé que esto dependería de la shell). Esto me hizo darme cuenta de que en whichrealidad es un shell incorporado y no una utilidad normal de Unix como había supuesto. Entonces debería editar mi pregunta y especificar Zsh. ¡Gracias por señalarme esto!
Adrian Petrescu
whichno está integrado, al menos no en Debian. Es un script de shell y parte de debianutils, por lo que funciona en zsh. Sin embargo, --skip-aliasno es una opción whichen Debian. ¿Hay diferentes variedades de whichflotar? Esto no parece ser un comando estandarizado.
Faheem Mitha
@Faheem Mitha: Es un zsh incorporado. Ver man zshbuiltins. que [-wpams] nombre ... Equivalente a donde -c.
Mikel
Sí, en Xubuntu bash, no está integrado y no tiene la --skip-aliasopción.
polym
En CentOS (y RHEL?) 6, es un ejecutable /usr/bin/whichmás un alias /etc/profile.dque le permite manejar alias pero --skip-aliasfunciona. Como resultado which whichmuestra el alias, ¡pero command which whichmuestra el ejecutable!
dave_thompson_085
0

Otra alternativa es command which vim, que funciona de la misma manera en ambos zshybash

Por ejemplo, en mi mac:

LOLcalhost :: ~ % command which grep
/usr/local/bin/grep
Zee Alexander
fuente
Ah lo suficientemente justo.
Zee Alexander
0

Ambos typey se whichcomportan de manera diferente según su tipo de shell.

En bash, whichexiste un comando en PATH. Busca el comando que proporcionas PATH. Bash builtin type -P(P for PATH) se comporta exactamente igual which.

En ZSH, tanto whichy typeson órdenes internas, y las funciones parciales de orden interna whence. which -pes lo que quieres Se fuerza una búsqueda de ruta. (la -Popción no está disponible para typeZSH).

de donde [-vcwfpamsS] [-x num] nombre ...

-pags

Haga una búsqueda de ruta para el nombre, incluso si se trata de un alias, palabra reservada, función de shell o incorporado.

Más del manual de ZSH.

que [-wpamsS] [-x num] nombre ...

Equivalente a donde -c.

Para omitir builtin whichy forzar el uso del comando whichdesde PATHZSH:

alias which="command which"
Simba
fuente