Necesito encontrar la ruta de un programa dado PATH
usando un script de shell. La ruta debe ser la ruta completa real del programa, que se puede pasar más tarde a una de las exec*
funciones, que no busca en PATH
sí misma, por ejemplo execv
.
Hay programas como kill
, que están disponibles como un programa real y un shell incorporado al mismo tiempo. Si este es el caso, necesito la ruta completa al programa real.
Hay varias utilidades que pueden encontrar un programa en el PATH
especificado en la Sección 2.9.1.1, Búsqueda de comandos y ejecución del estándar POSIX .
La hay which
, que no forma parte de ningún estándar. Puede ser un programa regular en algunos sistemas, mientras que algunos shells lo proporcionan. Parece estar disponible en la mayoría de los sistemas y shells, pero los shells con una versión incorporada, también solo devuelven el nombre del incorporado en lugar de la ruta al ejecutable. Además, no está estandarizado de ninguna manera y puede devolver cualquier salida y tomar diferentes opciones.
bash# which kill
/usr/bin/kill
dash# which kill
/usr/bin/kill
fish# which kill
/usr/bin/kill
mksh# which kill
/usr/bin/kill
tcsh# which kill
kill: shell built-in command.
zsh# which kill
kill: shell built-in command
Hay whence
, que es una de las conchas incorporadas. Pero no está disponible en muchos proyectiles. También devolverá el nombre del incorporado en lugar de la ruta al programa. Se -p
puede pasar A de dónde cambiar este comportamiento.
bash# whence kill
bash: whence: command not found
dash# whence kill
dash: 1: whence: not found
fish# whence kill
fish: Unknown command 'whence'
mksh# whence kill
kill
mksh# whence -p kill
/usr/bin/kill
tcsh# whence kill
whence: Command not found.
zsh# whence kill
kill
zsh# whence -p kill
/usr/bin/kill
Existe la command
construcción especificada por POSIX: 2008 . Desafortunadamente, también busca comandos regulares e incorporados y devolverá el nombre del incorporado en lugar de la ruta al programa sombreado por un incorporado del mismo nombre. Algunas conchas viejas aún no lo han implementado.
bash# command -v kill
kill
dash# command -v kill
kill
fish# command -v kill
/usr/bin/kill
mksh# command -v kill
kill
tcsh# command -v kill
command: Command not found.
zsh# command -v kill
kill
enable
se especifica en POSIX o no, pero si lo es, podría usarenable -n which
para deshabilitar el shell incorporadowhich
.realpath
enable
solo es proporcionado porbash
yzsh
type -p
. Tanto bash como dash le permiten decircommand
comando para ejecutar un ejecutable real, incluso si hay una función o incorporado con el mismo nombre.command
omite funciones (y alias) pero NO integra, como dice Q correctamente. Y no siempre puede usar un shebang porque no hay una ruta que obtenga un shell determinado, o incluso un shell POSIX, en todos los sistemas.Respuestas:
Solo búscalo tú mismo.
Probado en
bash
,dash
,ksh
,mksh
,zsh
Actualizar
Lo anterior es bueno para una secuencia de comandos independiente, sin embargo, si planea incorporar esto en una secuencia de comandos más grande, es posible que desee usar algo más como lo siguiente.
Esto es para que
IFS
se restaure después de encontrar la coincidencia, también se intercambiaexit
's porreturn
'fuente
IFS
variable? ¿No es suficiente tener esto configurado en el shell local? Hablando de local, ¿local IFS
sería portátil? Lo anterior puede interactuar mal si algo más está guardando IFS de la misma manera. Mirando esta pregunta en SE ,local
puede funcionar para la mayoría de los shells a pesar de no ser POSIX. Poner la versión original en una(…)
subshell también podría funcionar.