Al buscar la ruta a un archivo ejecutable o comprobar lo que sucedería si se introduce un nombre de comando en un shell de Unix, hay una plétora de diferentes servicios públicos ( which
, type
, command
, whence
, where
, whereis
, whatis
, hash
, etc).
A menudo escuchamos que se which
debe evitar. ¿Por qué? ¿Qué deberíamos usar en su lugar?
shell
history
which
portability
Stéphane Chazelas
fuente
fuente
which
suponen un contexto de shell interactivo. Esta pregunta está etiquetada / portabilidad. Así que interpreto la pregunta en este contexto como "qué usar en lugar dewhich
encontrar el primer ejecutable de un nombre dado en el$PATH
". La mayoría de las respuestas y razones en contra dewhich
tratar con alias, funciones y funciones, que en la mayoría de los scripts de shell portátiles del mundo real son solo de interés académico. Los alias definidos localmente no se heredan cuando se ejecuta un script de shell (a menos que lo obtenga.
).csh
(ywhich
sigue siendo uncsh
script en la mayoría de los Unices comerciales) se lee~/.cshrc
cuando no es interactivo. Es por eso que notarás que los scripts csh generalmente comienzan con#! /bin/csh -f
.which
no porque tiene como objetivo darle los alias, porque está destinado a ser una herramienta para usuarios (interactivos) decsh
. POSIX shells usuarios tienencommand -v
.(t)csh
(o no le importe si no le da el resultado correcto), usetype
o en sucommand -v
lugar . Vea las respuestas de por qué .stat $(which ls)
está mal por varias razones (faltan--
, faltan comillas), no solo el uso dewhich
). Tendrá que utilizarstat -- "$(command -v ls)"
. Eso suponels
que, de hecho, es un comando que se encuentra en el sistema de archivos (no un componente de su shell o función de alias).which
podría darle la ruta incorrecta (no la ruta que su shell ejecutaría si ingresarals
) o darle un alias como se define en la configuración de algunos otros shells ...which
implementaciones no le darían ni siquiera lasls
que se encontrarían en una búsqueda$PATH
(independientemente de lo quels
pueda invocar en su shell).sh -c 'command -v ls'
, ozsh -c 'rpm -q --whatprovides =ls'
es más probable que le den la respuesta correcta. El punto aquí es quewhich
es una herencia rota decsh
.Respuestas:
Aquí está todo lo que nunca pensó que nunca querría saber al respecto:
Resumen
Para obtener el nombre de ruta de un ejecutable en un script de shell similar a Bourne (hay algunas advertencias; ver más abajo):
Para averiguar si existe un comando dado:
En el indicador de un shell interactivo similar a Bourne:
El
which
comando es una herencia rota del C-Shell y es mejor dejarlo solo en los proyectiles tipo Bourne.Casos de uso
Hay una distinción entre buscar esa información como parte de un script o interactivamente en el indicador de comandos de shell.
En el indicador de comandos de shell, el caso de uso típico es: este comando se comporta de manera extraña, ¿estoy usando el correcto? ¿Qué sucedió exactamente cuando escribí
mycmd
? ¿Puedo mirar más allá de lo que es?En ese caso, desea saber qué hace su shell cuando invoca el comando sin invocarlo.
En los scripts de shell, tiende a ser bastante diferente. En un script de shell no hay ninguna razón por la que quieras saber dónde o qué es un comando si todo lo que quieres hacer es ejecutarlo. En general, lo que quiere saber es la ruta del archivo ejecutable, para que pueda obtener más información (como la ruta a otro archivo relativo a eso o leer información del contenido del archivo ejecutable en esa ruta).
Interactivamente, es posible que desee conocer todos los
my-cmd
comandos disponibles en el sistema, en scripts, rara vez.La mayoría de las herramientas disponibles (como suele ser el caso) han sido diseñadas para ser utilizadas de forma interactiva.
Historia
Un poco de historia primero.
Los primeros depósitos de Unix hasta finales de los 70 no tenían funciones ni alias. Solo la búsqueda tradicional de ejecutables en
$PATH
.csh
introdujo alias alrededor de 1978 (aunquecsh
se lanzó por primera vez en2BSD
mayo de 1979), y también el procesamiento de una.cshrc
para que los usuarios personalicen el shell (cada shell, como secsh
lee.cshrc
incluso cuando no es interactivo como en los scripts).Si bien el shell Bourne se lanzó por primera vez en Unix V7 a principios de 1979, el soporte de funciones solo se agregó mucho más tarde (1984 en SVR2) y, de todos modos, nunca tuvo algún
rc
archivo (.profile
es para configurar su entorno, no el shell per se ).csh
se hizo mucho más popular que el shell Bourne ya que (aunque tenía una sintaxis mucho peor que el shell Bourne) estaba agregando muchas más características convenientes y agradables para uso interactivo.En
3BSD
(1980), se agregó unwhich
script csh para que loscsh
usuarios ayudaran a identificar un ejecutable, y es un script apenas diferente que se puede encontrarwhich
en muchos Unices comerciales hoy en día (como Solaris, HP / UX, AIX o Tru64).Ese script lee al usuario
~/.cshrc
(como lo hacen todos loscsh
scripts a menos que se invoque concsh -f
), y busca los nombres de comando proporcionados en la lista de alias y en$path
(la matriz que secsh
basa en$PATH
).Aquí tienes,
which
llegó primero para el shell más popular en ese momento (ycsh
aún era popular hasta mediados de los 90), que es la razón principal por la que se documentó en los libros y todavía se usa ampliamente.Tenga en cuenta que, incluso para un
csh
usuario, esewhich
script csh no necesariamente le brinda la información correcta. Obtiene los alias definidos~/.cshrc
, no los que haya definido más adelante en el indicador o, por ejemplo, alsource
ingresar otrocsh
archivo y (aunque eso no sería una buena idea),PATH
podría redefinirse~/.cshrc
.Ejecutar ese
which
comando desde un shell Bourne aún buscaría los alias definidos en su~/.cshrc
, pero si no tiene uno porque no lo usacsh
, probablemente todavía obtendrá la respuesta correcta.No se agregó una funcionalidad similar al shell Bourne hasta 1984 en SVR2 con el
type
comando incorporado. El hecho de que esté integrado (a diferencia de un script externo) significa que puede brindarle la información correcta (hasta cierto punto) ya que tiene acceso a las partes internas del shell.El
type
comando inicial sufrió un problema similar alwhich
script en que no devolvió un estado de salida de falla si no se encontró el comando. Además, para los ejecutables, al contrariowhich
, genera algo así enls is /bin/ls
lugar de solo lo/bin/ls
que lo hace menos fácil de usar en los scripts.El shell Bourne de Unix Versión 8 (no lanzado en la naturaleza) tenía su
type
nombre incorporadowhatis
. Y el shell Plan9 (el sucesor de Unix)rc
(y sus derivados likeakanga
yes
) también lo tienenwhatis
.El shell Korn (un subconjunto en el que se basa la definición POSIX sh), desarrollado a mediados de los años 80 pero no ampliamente disponible antes de 1988, agregó muchas de las
csh
características (editor de línea, alias ...) en la parte superior del shell Bourne . Agregó su propiowhence
incorporado (además detype
) que tomó varias opciones (-v
para proporcionar unatype
salida detallada similar, y-p
buscar solo ejecutables (no alias / funciones ...)).Coincidiendo con la agitación con respecto a los problemas de derechos de autor entre AT&T y Berkeley, a finales de los 80 y principios de los 90 surgieron algunas implementaciones de software libre . Todo el shell Almquist (ash, que será el reemplazo del shell Bourne en BSD), la implementación de dominio público de ksh (pdksh),
bash
(patrocinado por la FSF),zsh
salió entre 1989 y 1991.Ash, aunque pretendía ser un reemplazo para el shell Bourne, no tuvo un
type
builtin incorporado hasta mucho más tarde (en NetBSD 1.3 y FreeBSD 2.3), aunque lo teníahash -v
. OSF / 1/bin/sh
tenía untype
incorporado que siempre devolvía 0 hasta OSF / 1 v3.x.bash
no agregó unwhence
pero agregó una-p
opción paratype
imprimir la ruta (type -p
sería comowhence -p
) e-a
informar todos los comandos coincidentes.tcsh
hechowhich
incorporado y ha añadido unwhere
comando de actuar comobash
'stype -a
.zsh
los tiene todos.El
fish
shell (2005) tiene untype
comando implementado como una función.Mientras
which
tanto, el script csh se eliminó de NetBSD (ya que estaba incorporado en tcsh y no era de mucha utilidad en otros shells), y la funcionalidad añadida awhereis
(cuando se invoca comowhich
, sewhereis
comporta como,which
excepto que solo busca ejecutables$PATH
). En OpenBSD y FreeBSD,which
también se cambió a uno escrito en C que solo busca comandos$PATH
.Implementaciones
Hay docenas de implementaciones de un
which
comando en varios Unices con diferente sintaxis y comportamiento.En Linux (además de los incorporados en
tcsh
yzsh
) encontramos varias implementaciones. En los sistemas Debian recientes, por ejemplo, es un simple script de shell POSIX que busca comandos en$PATH
.busybox
También tiene unwhich
comando.Hay una
GNU
which
que probablemente sea la más extravagante. Intenta extender lo que elwhich
script csh hizo a otros shells: puedes decirle cuáles son tus alias y funciones para que pueda darte una mejor respuesta (y creo que algunas distribuciones de Linux establecen algunos alias globales parabash
hacerlo). .zsh
tiene un par de operadores para expandir a la ruta de los ejecutables: el operador de=
expansión de nombre de archivo y el:c
modificador de expansión de historial (aquí aplicado a la expansión de parámetros ):zsh
, en elzsh/parameters
módulo también crea la tabla hash de comandos como lacommands
matriz asociativa:La
whatis
utilidad (excepto la de Unix V8 Bourne shell o Plan 9rc
/es
) no está realmente relacionada, ya que es solo para documentación (greps, la base de datos whatis, esa es la sinopsis de la página de manual).whereis
también se agregó3BSD
al mismo tiempo comowhich
si estuviera escritoC
, nocsh
y se usa para buscar al mismo tiempo, el ejecutable, la página de manual y la fuente, pero no se basa en el entorno actual. Entonces, de nuevo, eso responde a una necesidad diferente.Ahora, en el frente estándar, POSIX especifica los comandos
command -v
y-V
(que solían ser opcionales hasta POSIX.2008). UNIX especifica eltype
comando (sin opción). Eso es todo (where
,which
,whence
no se especifican en cualquier punto de vista)Hasta alguna versión,
type
ycommand -v
eran opcionales en la especificación de Linux Standard Base que explica por qué, por ejemplo, algunas versiones antiguas deposh
(aunque basadas en laspdksh
que tenían ambas) tampoco tenían.command -v
también se agregó a algunas implementaciones de shell Bourne (como en Solaris).Estado hoy
El estado actual es ese
type
ycommand -v
están en todas partes en todos los shells tipo Bourne (aunque, como lo señaló @jarno, tenga en cuenta la advertencia / errorbash
cuando no está en modo POSIX o algunos descendientes del shell Almquist a continuación en los comentarios).tcsh
es el único shell donde querrías usarwhich
(ya que no haytype
allí ywhich
está integrado).En los shells que no sean
tcsh
yzsh
, eswhich
posible que le indiquen la ruta del ejecutable dado siempre que no haya un alias o función con ese mismo nombre en ninguno de nuestros archivos de inicio de shell~/.cshrc
,~/.bashrc
o que no defina$PATH
en su~/.cshrc
. Si tiene un alias o una función definidos, puede o no informarle al respecto, o decirle algo incorrecto.Si desea conocer todos los comandos por un nombre de pila, no hay nada portátil. Lo usaría
where
entcsh
ozsh
,type -a
enbash
ozsh
,whence -a
en ksh93 y en otros shells, puede usarlotype
en combinación con lowhich -a
que puede funcionar.Recomendaciones
Obtener el nombre de ruta a un ejecutable
Ahora, para obtener el nombre de ruta de un ejecutable en un script, hay algunas advertencias:
sería la forma estándar de hacerlo.
Sin embargo, hay algunos problemas:
type
,which
,command -v
... todos utilizan la heurística para averiguar la ruta. Recorren los$PATH
componentes y encuentran el primer archivo que no es de directorio para el que tiene permiso de ejecución. Sin embargo, dependiendo del shell, cuando se trata de ejecutar el comando, muchos de ellos (Bourne, AT&T ksh, zsh, ash ...) simplemente los ejecutarán en el orden de$PATH
hasta que laexecve
llamada al sistema no regrese con un error . Por ejemplo, si$PATH
contiene/foo:/bar
y desea ejecutarls
, primero intentarán ejecutar/foo/ls
o si eso falla/bar/ls
. Ahora ejecución de/foo/ls
puede fallar porque no tiene permiso de ejecución, pero también por muchas otras razones, como que no es un ejecutable válido.command -v ls
informaría/foo/ls
si tiene permiso de ejecución/foo/ls
, pero la ejecuciónls
podría ejecutarse/bar/ls
si/foo/ls
no es un ejecutable válido.foo
es un incorporado o una función o alias,command -v foo
devuelvefoo
. Con algunos shells comoash
,pdksh
ozsh
, también puede regresarfoo
si$PATH
incluye la cadena vacía y hay unfoo
archivo ejecutable en el directorio actual. Hay algunas circunstancias en las que es posible que deba tener eso en cuenta. Tenga en cuenta, por ejemplo, que la lista de funciones integradas varía con la implementación del shell (por ejemplo, amount
veces está integrada para busyboxsh
) y, por ejemplo,bash
puede obtener funciones del entorno.$PATH
contiene componentes de ruta relativos (normalmente.
o la cadena vacía que se refieren al directorio actual pero podrían ser cualquier cosa), dependiendo del shell,command -v cmd
podría no generar una ruta absoluta. Por lo tanto, la ruta que obtienes en el momento en que correscommand -v
ya no será válida después de que estéscd
en otro lugar./opt/ast/bin
(a pesar de que la ruta exacta puede variar en diferentes sistemas, creo que) está en ti$PATH
, ksh93 hará unas pocas órdenes internas adicionales disponibles (chmod
,cmp
,cat
...), perocommand -v chmod
regresará/opt/ast/bin/chmod
incluso si ese camino doesn' t existe.Determinar si existe un comando
Para averiguar si un comando dado existe de manera estándar, puede hacer lo siguiente:
Donde uno podría querer usar
which
(t)csh
En
csh
ytcsh
, no tienes mucha opción. Entcsh
, eso está bien comowhich
está incorporado. Encsh
, ese será elwhich
comando del sistema , que puede no hacer lo que desea en algunos casos.buscar comandos solo en algunos shells
Un caso en el que podría tener sentido usarlo
which
es si desea conocer la ruta de un comando, ignorando las funciones o funciones potenciales de shell enbash
,csh
(notcsh
)dash
oBourne
scripts de shell, es decir, shells que no tienenwhence -p
(likeksh
ozsh
) ,command -ev
(likeyash
),whatis -p
(rc
,akanga
) o un builtinwhich
(liketcsh
ozsh
) en sistemas dondewhich
está disponible y no es elcsh
script.Si se cumplen esas condiciones, entonces:
le daría la trayectoria de la primera
echo
en$PATH
(excepto en casos de esquina), con independencia de queecho
también pasa a ser un / alias / función de línea de orden interna o no.En otras conchas, preferirías:
echo==echo
oecho=$commands[echo]
oecho=${${:-echo}:c}
echo=$(whence -p echo)
echo=$(command -ev echo)
echo=`whatis -p echo`
(cuidado con los caminos con espacios)set echo (type -fp echo)
Tenga en cuenta que si todo lo que quiere hacer es ejecutar ese
echo
comando, no tiene que obtener su ruta, simplemente puede hacer:Por ejemplo, con
tcsh
, para evitar quewhich
se use el incorporado :cuando necesitas un comando externo
Otro caso en el que es posible que desee utilizar
which
es cuando realmente necesita un comando externo. POSIX requiere que todos los componentes integrados de shell (comocommand
) también estén disponibles como comandos externos, pero desafortunadamente ese no es el casocommand
en muchos sistemas. Por ejemplo, es raro encontrar uncommand
comando en sistemas operativos basados en Linux, mientras que la mayoría de ellos tienen unwhich
comando (aunque diferentes con diferentes opciones y comportamientos).Los casos en los que es posible que desee un comando externo estarían donde ejecute un comando sin invocar un shell POSIX.
El
system("some command line")
,popen()
... funciones de C o varias lenguas no invocan una cáscara de analizar esa línea de comandos, por lo quesystem("command -v my-cmd")
hacen el trabajo en ellos. Una excepción a eso sería laperl
que optimiza el shell si no ve ningún carácter especial del shell (que no sea espacio). Eso también se aplica a su operador de backtick:La adición de lo
:;
anterior obligaperl
a invocar un caparazón allí. Al usarwhich
, no tendrías que usar ese truco.fuente
which
es uncsh
guión en muchos Unices comerciales. La razón es histórica, es por eso que di la historia, para que la gente entienda de dónde vino, por qué la gente se acostumbró a usarla y por qué en realidad no hay razón para que la uses. Y sí, algunas personas usan (t) csh. Todavía no todos usan Linuxwhich
, a diferencia de las cosas que podría estar tratando de usarwhich
, el historial dewhich
, implementacioneswhich
, otros comandos para realizar tareas relacionadas o razones para usar realmentewhich
? ¿Por qué son mejores los otros comandos ? ¿De qué hacen diferentewhich
? ¿Cómo evitan sus trampas? Esta respuesta realmente gasta más palabras en los problemas con las alternativas que los problemas conwhich
.command -v
no verifica el permiso de ejecución, al menos si lo llama por un argumento de nombre de archivo puro sin ruta. Probé con dash 0.5.8 y GNU bash 4.3.48.touch /usr/bin/mytestfile
y luego lo ejecutocommand -v mytestfile
, me dará la ruta (mientraswhich mytestfile
que no).bash
se instalará en un archivo no ejecutable si no puede encontrar uno ejecutable, por lo que está "bien" (aunque en la práctica uno preferiríacommand -v
/type
devolvería un error) ya que ese es el comando que intentaría ejecutar cuando ejecutamytestfile
, pero eldash
el comportamiento es defectuoso, ya que si hay un no ejecutablecmd
antes que uno ejecutable,command -v
devuelve el no ejecutable mientras que la ejecucióncmd
ejecutaría el ejecutable (el incorrecto también se tritura). FreeBSDsh
(también basado enash
) tiene el mismo error. zsh, yash, ksh, mksh, bash como sh están bien.which
Ya se han explicado las razones por las que uno no quiere usar , pero aquí hay algunos ejemplos en algunos sistemas dondewhich
realmente falla.En los shells tipo Bourne, estamos comparando la salida de
which
con la salida detype
(altype
ser un shell incorporado, está destinado a ser la verdad fundamental, ya que es el shell que nos dice cómo invocaría un comando).Muchos casos son casos de esquina , pero tenga en cuenta que
which
/type
se usan a menudo en casos de esquina (para encontrar la respuesta a un comportamiento inesperado como: ¿por qué ese comando se comporta así, a quién estoy llamando? ).La mayoría de los sistemas, la mayoría de los shells tipo Bourne: funciones
El caso más obvio es para las funciones:
La razón es que
which
solo informa sobre ejecutables y, a veces, sobre alias (aunque no siempre los de su shell), no sobre funciones.El GNU cuya página de manual tiene un ejemplo roto (como se olvidaron de citar
$@
) sobre cómo usarlo para informar funciones también, pero al igual que para los alias, porque no implementa un analizador sintáctico de shell, se engaña fácilmente:La mayoría de los sistemas, la mayoría de las conchas tipo Bourne: builtins
Otro caso es obvio órdenes internas o palabras clave, ya que
which
siendo un comando externo no tiene manera de saber qué órdenes internas de su cáscara tiene (y algunas conchas comozsh
,bash
oksh
puede cargar dinámicamente órdenes internas):(eso no se aplica a
zsh
dóndewhich
está incorporado)Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5.1 y muchos otros:
Esto se debe a que en la mayoría de los Unices comerciales,
which
(como en la implementación original en 3BSD) hay uncsh
script que lee~/.cshrc
. Los alias que informará son los definidos allí, independientemente de los alias que haya definido actualmente y del shell que esté utilizando.En HP / UX o Tru64:
(Las versiones de Solaris y AIX han solucionado ese problema guardando
$path
antes de leerlo~/.cshrc
y restableciéndolo antes de buscar los comandos)O:
(por supuesto, al ser un
csh
script, no puede esperar que funcione con argumentos que contienen espacios ...)CentOS 6.4, bash
En ese sistema, hay un alias definido en todo el sistema que envuelve el
which
comando GNU .La salida falsa es porque
which
lee la salida debash
'salias
pero no sabe cómo analizar correctamente y utiliza la heurística (un alias por línea, busca la encontró por primera vez después de un comando|
,;
,&
...)Lo peor en CentOS es que
zsh
tiene unwhich
comando incorporado perfectamente bien, pero CentOS logró romperlo al reemplazarlo con un alias que no funciona para GNUwhich
.Debian 7.0, ksh93:
(aunque se aplica a la mayoría de los sistemas con muchos shells)
En Debian,
/bin/which
es un/bin/sh
script. En mi caso,sh
serdash
pero es lo mismo cuando lo esbash
.Un desarmado
PATH
no es deshabilitar laPATH
búsqueda, sino que significa usar la RUTA predeterminada del sistema, que desafortunadamente en Debian, nadie está de acuerdo (dash
ybash
have/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
,zsh
has/bin:/usr/bin:/usr/ucb:/usr/local/bin
,ksh93
has/bin:/usr/bin
,mksh
has/usr/bin:/bin
($(getconf PATH)
),execvp()
(like inenv
) has:/bin:/usr/bin
(yes, ¡primero busca en el directorio actual! )).Es por eso que
which
se equivoca más arriba ya que está usandodash
el valor predeterminadoPATH
que es diferente delksh93
deNo es mejor con GNU
which
que informa:(curiosamente, en efecto, hay una
/usr/local/bin/which
en mi sistema, que es en realidad unaakanga
secuencia de comandos que viene conakanga
(unrc
derivado de la cáscara cuando el incumplimientoPATH
es/usr/ucb:/usr/bin:/bin:.
))bash, cualquier sistema:
Al que Chris se refiere en su respuesta :
También después de llamar
hash
manualmente:Ahora un caso donde
which
ya vecestype
falla:Ahora, con algunas conchas:
Con otros:
Ni
which
tampocotype
pueden saber de antemano queb/foo
no se puede ejecutar. Algunas conchas comobash
,ksh
oyash
, cuando se invocafoo
de hecho va a tratar de ejecutarb/foo
e informar de un error, mientras que otros (comozsh
,ash
,csh
,Bourne
,tcsh
) se ejecutarána/foo
sobre el fracaso de laexecve()
llamada al sistema deb/foo
.fuente
mksh
en realidad usa algo diferente para el valor predeterminado$PATH
: primero,_PATH_DEFPATH
se usa la constante de tiempo de compilación del sistema operativo (más comúnmente en los BSD), luego,confstr(_CS_PATH, …)
se usa (POSIX), y si ambos no existen o fallan,/bin:/usr/bin:/sbin:/usr/sbin
se usa.ls
es una función que está utilizandols
desde PATH. Ywhich
está bien decirle cuál se usa/usr/bin/ls
o/usr/local/bin/ls
. No veo "¿Por qué no utiliza la cual" ....which ls
me dará/bin/ls
independientemente de si lals
función llama/bin/ls
o/opt/gnu/bin/ls
odir
o nada en absoluto. IOW,which
(lo que implementaciones, IMMV) está dando algo irrelevantels
es una función. Yo sé que mils
función está llamandols
desdePATH
. Ahorawhich
me dice dónde está el archivo. Solo ve un caso de uso único: "¿Qué haría mi shell con este comando?" Para este caso de usowhich
es incorrecto, correcto. Pero hay otros casos de uso donde (GNU)which
es exactamente lo correcto.which
implementación. Algunos le dirán que es un alias (si tiene un alias configurado, o si hay uno~/.cshrc
en su hogar que tiene dicho alias), algunos le darán una ruta pero la incorrecta en algunas condiciones.sh -c 'command -v ls'
, aunque no es perfecto, es más probable que le dé la respuesta correcta a ese requisito diferente (y también es estándar).Una cosa que (desde mi rápida lectura) parece que Stephane no mencionó es que
which
no tiene idea sobre la tabla hash de ruta de acceso de su shell. Esto tiene el efecto de que puede devolver un resultado que no es representativo de lo que realmente se ejecuta, lo que lo hace ineficaz en la depuración.fuente
En el espíritu de UNIX: haga que cada programa haga una cosa bien.
Si el objetivo es responder: ¿Qué ejecutable existe con este nombre?
El programa ejecutable que se proporciona con los sistemas Debian es una buena respuesta. El que proporcionaba csh incluía alias, que es una fuente de problemas. El que proporcionan algunos proyectiles como una construcción interna tiene un objetivo diferente. Utilice ese ejecutable o use el script proporcionado al final de esta respuesta.
Si se utiliza este script, lo que responde es limpio, simple y útil.
Este objetivo coincidirá con la primera oración de su pregunta:
Si tiene un sistema que no tiene un ejecutable llamado que (la mayoría de los sistemas de Linux tienen uno), puede crear uno
~/bin/which
antes/bin/
en la RUTA para que el sistema de anulación de ejecutables personales sea el que se encuentra al final de esta publicación:Ese ejecutable enumerará (por defecto) todos los ejecutables encontrados en la RUTA. Si solo se requiere el primero, la opción
-f
está disponible.En este punto caemos en un objetivo diferente:
qué ejecutará el shell (después del análisis)
Eso viene de tu segunda oración:
Este segundo tema intenta encontrar una buena respuesta a una pregunta que es bastante difícil de responder. Los proyectiles tienen vistas divergentes, casos de esquina y (como mínimo) diferentes interpretaciones. Agregando a eso:
Y claro, todos los intentos coinciden con ese objetivo.
¿Evitar cuál?
Me pregunto: ¿por qué debería decirse eso si
which
funciona bien (al menos en Debian)?En el espíritu de UNIX: haga que cada programa haga una cosa bien.
El programa externo
which
está haciendo una cosa: encontrar el primer ejecutable en la RUTA que tenga el mismo nombre que el nombre del comando . Y lo está haciendo razonablemente bien.No conozco ningún otro programa o utilidad que responda a esta pregunta de una manera más fundamental. Como tal, es útil y podría usarse cuando sea necesario.
La alternativa más cercana parece ser:,
command -pv commandName
pero eso también informará sobre alias y construcciones. No es la misma respuesta.Por supuesto,
which
es limitado, no responde todas las preguntas, ninguna herramienta podría hacer eso (bueno, todavía no ...). Pero es útil cuando se usa para responder la pregunta para la que fue diseñada (la que se encuentra arriba). Mucho comoed
fue limitado y luegosed
apareció (ovi
/vim
). O likeawk
fue limitado e hizo que Perl apareciera y se extendiera. Sin embargo,ed
,sed
y / oawk
tienen casos de uso específicos en los quevim
operl
son no las mejores herramientas.Probablemente porque
which
responde solo una parte de la pregunta que un usuario de shell podría hacer:¿Qué se ejecuta cuando escribo un nombre de comando?
Externo que
Que debería estar disponible (en muchos sistemas) como un ejecutable externo.
La única forma segura de llamar a esa herramienta externa es usar env para salir del shell y luego llamar
which
(que funciona en todos los shells):O use la ruta completa a
which
(que puede variar en diferentes sistemas):¿Por qué es eso
hack
necesario? Debido a que algunos shells (especialmente zsh) se escondenwhich
:Ser una herramienta externa (como
env
) explica perfectamente por qué no informará información interna del shell. Como alias, funciones, incorporados, incorporados especiales, variables de shell (no exportadas), etc.La salida vacía de
ll
(un alias común parall='ls -l'
) indica quell
no está relacionado con un programa ejecutable, o al menos, que no hay un archivo ejecutable nombradoll
en la RUTA. El uso dell
debería llamar a otra cosa, en este caso, un alias:type
ycommand
Los comandos
type
ycommand -v
son solicitados por POSIX. Se debe esperar que trabajen en la mayoría de los depósitos, y lo hacen, excepto en csh, tcsh, fish y rc.Ambos comandos podrían usarse para proporcionar otro punto de vista de qué comando se ejecutará.
whence
`where
`whereis
`whatis
`hash
Entonces, hay
whence
,where
,whereis
,whatis
,hash
, y algunos otros. Todas las respuestas diferentes a preguntas similares. Todos trabajan de diferentes maneras en diferentes conchas. Probablemente,whence
es el más común despuéstype
. Los otros son soluciones especiales que responden a la misma pregunta de diferentes maneras.Probablemente
which
primero en saber si existe un archivo ejecutable con el nombre de la CommandName , a continuación,type
ycommand
a continuación, si el CommandName no se ha encontrado todavía:whence
,where
,whereis
,whatis
,hash
en ese orden.Script de shell para proporcionar un
which
ejecutable.fuente
Nunca he escuchado eso. Por favor proporcione ejemplos específicos. ¡Me preocuparía su distribución de Linux y los paquetes de software instalados, ya que es de donde
which
viene!SLES 11.4 x86-64
en tcsh versión 6.18.01:
en la versión bash 3.2-147:
which
forma parte de util-linux, un paquete estándar distribuido por Linux Kernel Organization para su uso como parte del sistema operativo Linux. También proporciona estos otros archivosmi
util-linux
es la versión 2.19. Las notas de la versión se pueden encontrar fácilmente en la versión v2.13 con fecha (28 de agosto de 2007). No estoy seguro de cuál era el objetivo o el objetivo de esto, ciertamente no fue respondido en ese largo asunto votado 331 veces.fuente
which -v
muestra, ese es GNU que (el extravagante mencionado en la otra respuesta y no es específico para Linux), no util-linux, que AFAIK nunca incluyó unawhich
utilidad. util-linux 2.19 es de 2011, GNU que 2.19 es de 2008.