El orden de los ejecutables comenzó en bash

14

Si ejecuto el testcomando en bash, testse inicia la utilidad incorporada (evalúa la expresión condicional):

$ type test
test is a shell builtin
$ type -a test
test is a shell builtin
test is /usr/local/bin/test
test is /usr/bin/test
$ 

Sin embargo, como se ve en el resultado type -a testanterior, hay otro testen el directorio / usr / local / bin y otro en el directorio / usr / bin. ¿Cómo se ordenan los ejecutables, es decir, siempre se prefieren los comandos integrados y luego el resto de los comandos dependen del orden del directorio en la variable $ PATH? Además, ¿es posible cambiar el orden de los ejecutables iniciados, por ejemplo, si escribo test, entonces / usr / bin / test se inicia en lugar de bash-builtin test?

Martín
fuente
Puede especificar la ruta completa al llamar al comando, por ejemplo, /usr/bin/test -f "$file"...
jasonwryan
@jasonwryan Soy consciente de esto, pero solo estoy interesado si hay una manera de cambiar el orden de ejecución de los ejecutables.
Martin

Respuestas:

25

La prioridad más alta es bash alias, luego incorporaciones especiales (solo en modo POSIX), luego funciones, luego incorporaciones, luego una búsqueda $PATH.

Para ejecutar un builtin, use builtin test.
Para ejecutar una aplicación externa, utilice una ruta explícita: /bin/test.
Para ignorar funciones y alias, use command test.
Para omitir solo el alias, use \testo cualquier otro tipo de expansión.

Es posible deshabilitar / habilitar una función integrada con enable test.

(Actualizado de acuerdo con los comentarios a continuación)
(Se corrigió la edición de administrador incorrecta que bash ha disableincorporado, de hecho, solo la hay enable)

gena2x
fuente
1
@ 1_CR gena2x es correcto. Mi respuesta omitió construcciones especiales, que tienen prioridad sobre las funciones según POSIX (aunque algunos shells no son compatibles; bash solo cumple en modo POSIX).
Gilles 'SO- deja de ser malvado'
1
Edición sugerida: los alias se deshabilitan cuando cita el comando (o cualquier parte del mismo), como en \testo 'test'o tes't'.
John Kugelman
2
Esa no es una imagen completa. Parece cualquier tipo de expansión (en el manual de bash, toda la sustitución, tilde expansión y así sucesivamente llamada expansión ) desactiva los alias. Lo intenté.
gena2x
1
Presupuesto de la página de manual de bash:.. "La primera palabra de cada comando simple, si no indicada, se comprueba para ver si tiene un alias Si es así, esa palabra se sustituye por el texto del alias Los personajes /, $, acento grave, y =y cualquiera de los metacaracteres de shell o los caracteres entre comillas mencionados anteriormente pueden no aparecer en un nombre de alias ".
John Kugelman
2
+1 para obtener sugerencias para ayudarme a encontrar la fuente de esta información: se encuentra en la página de manual de bash, en la sección EJECUCIÓN DE MANDOS, párrafos segundo y tercero.
twan163
6

Los comandos integrados siempre se prefieren a los comandos externos. La razón es que el comando incorporado es más rápido (y en algunos casos, como cdo , solo el comando incorporado puede tener el efecto deseado).test -o BASH_OPTION

A veces, el comando externo puede tener capacidades que el shell incorporado no tiene. En ese caso, puede llamar al comando externo dando una ruta explícita (es decir, que contenga una barra inclinada) (esto evita cualquier preocupación sobre el orden $PATH). Si no desea codificar la ruta externa pero desea evitar el uso de la función incorporada, puede usar "$(type -P test)"(nota mayúscula P) en bash, "$(whence -p test)"en ksh y =testen zsh. Otra forma de forzar el uso de un comando externo es usar el commandbuiltin ( command -p test …) o pasar por la envutilidad ( env test …).

En zsh, puede deshabilitar un incorporado con disable test. Esto es permanente (para el shell o subshell actual) hasta que el builtin se vuelva a habilitar enable test. En bash, puede hacer lo mismo con enable -n testdeshabilitar y enable testvolver a habilitar.

Puede usar un alias o función para forzar la ejecución de un comando diferente, por ejemplo alias test=/usr/bin/testo test () { /usr/bin/test "$@"; }. Si tiene ese alias, puede evitar su uso citando cualquier parte del mismo, por ejemplo \test, realizará la función normal / incorporado / búsqueda externa. Tenga en cuenta que dependiendo del shell y su configuración, las definiciones de alias en una función pueden expandirse cuando se lee una función o cuando se ejecuta. Si ha definido una función, puede usarla command testpara evitar la búsqueda de funciones, así como la búsqueda de alias (por lo que aquí testse invocará el valor incorporado a menos que esté deshabilitado).

Gilles 'SO- deja de ser malvado'
fuente
¿No envsería apropiado aquí también?
Steven Penny el
entonces, si el shell se ejecuta desde BusyBox, ¿se consideran otros comandos usualmente externos del mismo BusyBox como componentes internos? Por ejemplo, agregué completo dfa una RUTA en la primera posición, eliminé el alias 'df', which dfmuestra / opt / bin / df, pero df ejecuta / bin / df -> busybox
papo
@papo which dfno necesariamente te muestra lo que se dfejecuta. unix.stackexchange.com/questions/85249/…
Gilles 'SO- deja de ser malvado'