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 whichdebe evitar. ¿Por qué? ¿Qué deberíamos usar en su lugar?
shell
history
which
portability
Stéphane Chazelas
fuente
fuente

whichsuponen un contexto de shell interactivo. Esta pregunta está etiquetada / portabilidad. Así que interpreto la pregunta en este contexto como "qué usar en lugar dewhichencontrar el primer ejecutable de un nombre dado en el$PATH". La mayoría de las respuestas y razones en contra dewhichtratar 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(ywhichsigue siendo uncshscript en la mayoría de los Unices comerciales) se lee~/.cshrccuando no es interactivo. Es por eso que notarás que los scripts csh generalmente comienzan con#! /bin/csh -f.whichno 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), usetypeo en sucommand -vlugar . 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 suponelsque, de hecho, es un comando que se encuentra en el sistema de archivos (no un componente de su shell o función de alias).whichpodrí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 ...whichimplementaciones no le darían ni siquiera laslsque se encontrarían en una búsqueda$PATH(independientemente de lo quelspueda 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 quewhiches 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
whichcomando 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-cmdcomandos 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.cshintrodujo alias alrededor de 1978 (aunquecshse lanzó por primera vez en2BSDmayo de 1979), y también el procesamiento de una.cshrcpara que los usuarios personalicen el shell (cada shell, como secshlee.cshrcincluso 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
rcarchivo (.profilees para configurar su entorno, no el shell per se ).cshse 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ó unwhichscript csh para que loscshusuarios ayudaran a identificar un ejecutable, y es un script apenas diferente que se puede encontrarwhichen muchos Unices comerciales hoy en día (como Solaris, HP / UX, AIX o Tru64).Ese script lee al usuario
~/.cshrc(como lo hacen todos loscshscripts 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 secshbasa en$PATH).Aquí tienes,
whichllegó primero para el shell más popular en ese momento (ycshaú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
cshusuario, esewhichscript 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, alsourceingresar otrocsharchivo y (aunque eso no sería una buena idea),PATHpodría redefinirse~/.cshrc.Ejecutar ese
whichcomando 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
typecomando 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
typecomando inicial sufrió un problema similar alwhichscript 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/lslugar de solo lo/bin/lsque 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
typenombre incorporadowhatis. Y el shell Plan9 (el sucesor de Unix)rc(y sus derivados likeakangayes) 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
cshcaracterísticas (editor de línea, alias ...) en la parte superior del shell Bourne . Agregó su propiowhenceincorporado (además detype) que tomó varias opciones (-vpara proporcionar unatypesalida detallada similar, y-pbuscar 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),zshsalió entre 1989 y 1991.Ash, aunque pretendía ser un reemplazo para el shell Bourne, no tuvo un
typebuiltin incorporado hasta mucho más tarde (en NetBSD 1.3 y FreeBSD 2.3), aunque lo teníahash -v. OSF / 1/bin/shtenía untypeincorporado que siempre devolvía 0 hasta OSF / 1 v3.x.bashno agregó unwhencepero agregó una-popción paratypeimprimir la ruta (type -psería comowhence -p) e-ainformar todos los comandos coincidentes.tcshhechowhichincorporado y ha añadido unwherecomando de actuar comobash'stype -a.zshlos tiene todos.El
fishshell (2005) tiene untypecomando implementado como una función.Mientras
whichtanto, 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, sewhereiscomporta como,whichexcepto que solo busca ejecutables$PATH). En OpenBSD y FreeBSD,whichtambién se cambió a uno escrito en C que solo busca comandos$PATH.Implementaciones
Hay docenas de implementaciones de un
whichcomando en varios Unices con diferente sintaxis y comportamiento.En Linux (además de los incorporados en
tcshyzsh) encontramos varias implementaciones. En los sistemas Debian recientes, por ejemplo, es un simple script de shell POSIX que busca comandos en$PATH.busyboxTambién tiene unwhichcomando.Hay una
GNUwhichque probablemente sea la más extravagante. Intenta extender lo que elwhichscript 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 parabashhacerlo). .zshtiene un par de operadores para expandir a la ruta de los ejecutables: el operador de=expansión de nombre de archivo y el:cmodificador de expansión de historial (aquí aplicado a la expansión de parámetros ):zsh, en elzsh/parametersmódulo también crea la tabla hash de comandos como lacommandsmatriz asociativa:La
whatisutilidad (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).whereistambién se agregó3BSDal mismo tiempo comowhichsi estuviera escritoC, nocshy 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 -vy-V(que solían ser opcionales hasta POSIX.2008). UNIX especifica eltypecomando (sin opción). Eso es todo (where,which,whenceno se especifican en cualquier punto de vista)Hasta alguna versión,
typeycommand -veran opcionales en la especificación de Linux Standard Base que explica por qué, por ejemplo, algunas versiones antiguas deposh(aunque basadas en laspdkshque tenían ambas) tampoco tenían.command -vtambién se agregó a algunas implementaciones de shell Bourne (como en Solaris).Estado hoy
El estado actual es ese
typeycommand -vestán en todas partes en todos los shells tipo Bourne (aunque, como lo señaló @jarno, tenga en cuenta la advertencia / errorbashcuando no está en modo POSIX o algunos descendientes del shell Almquist a continuación en los comentarios).tcshes el único shell donde querrías usarwhich(ya que no haytypeallí ywhichestá integrado).En los shells que no sean
tcshyzsh, eswhichposible 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,~/.bashrco que no defina$PATHen 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
whereentcshozsh,type -aenbashozsh,whence -aen ksh93 y en otros shells, puede usarlotypeen combinación con lowhich -aque 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$PATHcomponentes 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$PATHhasta que laexecvellamada al sistema no regrese con un error . Por ejemplo, si$PATHcontiene/foo:/bary desea ejecutarls, primero intentarán ejecutar/foo/lso si eso falla/bar/ls. Ahora ejecución de/foo/lspuede 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 lsinformaría/foo/lssi tiene permiso de ejecución/foo/ls, pero la ejecuciónlspodría ejecutarse/bar/lssi/foo/lsno es un ejecutable válido.fooes un incorporado o una función o alias,command -v foodevuelvefoo. Con algunos shells comoash,pdkshozsh, también puede regresarfoosi$PATHincluye la cadena vacía y hay unfooarchivo 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, amountveces está integrada para busyboxsh) y, por ejemplo,bashpuede obtener funciones del entorno.$PATHcontiene 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 cmdpodría no generar una ruta absoluta. Por lo tanto, la ruta que obtienes en el momento en que correscommand -vya no será válida después de que estéscden 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 chmodregresará/opt/ast/bin/chmodincluso 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)cshEn
cshytcsh, no tienes mucha opción. Entcsh, eso está bien comowhichestá incorporado. Encsh, ese será elwhichcomando 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
whiches si desea conocer la ruta de un comando, ignorando las funciones o funciones potenciales de shell enbash,csh(notcsh)dashoBournescripts de shell, es decir, shells que no tienenwhence -p(likekshozsh) ,command -ev(likeyash),whatis -p(rc,akanga) o un builtinwhich(liketcshozsh) en sistemas dondewhichestá disponible y no es elcshscript.Si se cumplen esas condiciones, entonces:
le daría la trayectoria de la primera
echoen$PATH(excepto en casos de esquina), con independencia de queechotambién pasa a ser un / alias / función de línea de orden interna o no.En otras conchas, preferirías:
echo==echooecho=$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
echocomando, no tiene que obtener su ruta, simplemente puede hacer:Por ejemplo, con
tcsh, para evitar quewhichse use el incorporado :cuando necesitas un comando externo
Otro caso en el que es posible que desee utilizar
whiches 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 casocommanden muchos sistemas. Por ejemplo, es raro encontrar uncommandcomando en sistemas operativos basados en Linux, mientras que la mayoría de ellos tienen unwhichcomando (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 laperlque 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 obligaperla invocar un caparazón allí. Al usarwhich, no tendrías que usar ese truco.fuente
whiches uncshguió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 -vno 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/mytestfiley luego lo ejecutocommand -v mytestfile, me dará la ruta (mientraswhich mytestfileque no).bashse 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/typedevolvería un error) ya que ese es el comando que intentaría ejecutar cuando ejecutamytestfile, pero eldashel comportamiento es defectuoso, ya que si hay un no ejecutablecmdantes que uno ejecutable,command -vdevuelve el no ejecutable mientras que la ejecucióncmdejecutarí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.whichYa se han explicado las razones por las que uno no quiere usar , pero aquí hay algunos ejemplos en algunos sistemas dondewhichrealmente falla.En los shells tipo Bourne, estamos comparando la salida de
whichcon la salida detype(altypeser 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/typese 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
whichsolo 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
whichsiendo un comando externo no tiene manera de saber qué órdenes internas de su cáscara tiene (y algunas conchas comozsh,bashokshpuede cargar dinámicamente órdenes internas):(eso no se aplica a
zshdóndewhichestá 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 uncshscript 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
$pathantes de leerlo~/.cshrcy restableciéndolo antes de buscar los comandos)O:
(por supuesto, al ser un
cshscript, 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
whichcomando GNU .La salida falsa es porque
whichlee la salida debash'saliaspero 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
zshtiene unwhichcomando 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/whiches un/bin/shscript. En mi caso,shserdashpero es lo mismo cuando lo esbash.Un desarmado
PATHno es deshabilitar laPATHbúsqueda, sino que significa usar la RUTA predeterminada del sistema, que desafortunadamente en Debian, nadie está de acuerdo (dashybashhave/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin,zshhas/bin:/usr/bin:/usr/ucb:/usr/local/bin,ksh93has/bin:/usr/bin,mkshhas/usr/bin:/bin($(getconf PATH)),execvp()(like inenv) has:/bin:/usr/bin(yes, ¡primero busca en el directorio actual! )).Es por eso que
whichse equivoca más arriba ya que está usandodashel valor predeterminadoPATHque es diferente delksh93deNo es mejor con GNU
whichque informa:(curiosamente, en efecto, hay una
/usr/local/bin/whichen mi sistema, que es en realidad unaakangasecuencia de comandos que viene conakanga(unrcderivado de la cáscara cuando el incumplimientoPATHes/usr/ucb:/usr/bin:/bin:.))bash, cualquier sistema:
Al que Chris se refiere en su respuesta :
También después de llamar
hashmanualmente:Ahora un caso donde
whichya vecestypefalla:Ahora, con algunas conchas:
Con otros:
Ni
whichtampocotypepueden saber de antemano queb/foono se puede ejecutar. Algunas conchas comobash,kshoyash, cuando se invocafoode hecho va a tratar de ejecutarb/fooe informar de un error, mientras que otros (comozsh,ash,csh,Bourne,tcsh) se ejecutarána/foosobre el fracaso de laexecve()llamada al sistema deb/foo.fuente
mkshen realidad usa algo diferente para el valor predeterminado$PATH: primero,_PATH_DEFPATHse 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/sbinse usa.lses una función que está utilizandolsdesde PATH. Ywhichestá bien decirle cuál se usa/usr/bin/lso/usr/local/bin/ls. No veo "¿Por qué no utiliza la cual" ....which lsme dará/bin/lsindependientemente de si lalsfunción llama/bin/lso/opt/gnu/bin/lsodiro nada en absoluto. IOW,which(lo que implementaciones, IMMV) está dando algo irrelevantelses una función. Yo sé que milsfunción está llamandolsdesdePATH. Ahorawhichme 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 usowhiches incorrecto, correcto. Pero hay otros casos de uso donde (GNU)whiches exactamente lo correcto.whichimplementación. Algunos le dirán que es un alias (si tiene un alias configurado, o si hay uno~/.cshrcen 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
whichno 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/whichantes/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
-festá 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
whichfunciona bien (al menos en Debian)?En el espíritu de UNIX: haga que cada programa haga una cosa bien.
El programa externo
whichestá 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 commandNamepero eso también informará sobre alias y construcciones. No es la misma respuesta.Por supuesto,
whiches 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 comoedfue limitado y luegosedapareció (ovi/vim). O likeawkfue limitado e hizo que Perl apareciera y se extendiera. Sin embargo,ed,sedy / oawktienen casos de uso específicos en los quevimoperlson no las mejores herramientas.Probablemente porque
whichresponde 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
hacknecesario? 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 quellno está relacionado con un programa ejecutable, o al menos, que no hay un archivo ejecutable nombradollen la RUTA. El uso delldebería llamar a otra cosa, en este caso, un alias:typeycommandLos comandos
typeycommand -vson 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`hashEntonces, 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,whencees el más común despuéstype. Los otros son soluciones especiales que responden a la misma pregunta de diferentes maneras.Probablemente
whichprimero en saber si existe un archivo ejecutable con el nombre de la CommandName , a continuación,typeycommanda continuación, si el CommandName no se ha encontrado todavía:whence,where,whereis,whatis,hashen ese orden.Script de shell para proporcionar un
whichejecutable.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
whichviene!SLES 11.4 x86-64
en tcsh versión 6.18.01:
en la versión bash 3.2-147:
whichforma 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-linuxes 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 -vmuestra, 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ó unawhichutilidad. util-linux 2.19 es de 2011, GNU que 2.19 es de 2008.