Ordre des exécutables démarré dans bash

14

Si j'exécute la testcommande dans bash, test(évalue l'expression conditionnelle) l'utilitaire intégré est démarré:

$ 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
$ 

Cependant, comme vu dans la sortie de type -a testci-dessus, il y en a un autre testdans le répertoire / usr / local / bin et encore un autre dans le répertoire / usr / bin. Comment les exécutables sont-ils ordonnés, c'est-à-dire que les commandes intégrées sont toujours préférées et que le reste des commandes dépend de l'ordre du répertoire dans la variable $ PATH? De plus, est-il possible de changer l'ordre des exécutables démarrés, par exemple si je tape test, alors / usr / bin / test est démarré au lieu de bash-builtin test?

Martin
la source
Vous pouvez spécifier le chemin complet lors de l'appel de la commande, par exemple., /usr/bin/test -f "$file"...
jasonwryan
@jasonwryan J'en suis conscient, mais je suis simplement intéressé s'il existe un moyen de changer l'ordre des exécutables démarré.
Martin

Réponses:

25

La priorité la plus élevée est l'alias bash, puis les fonctions spéciales (uniquement en mode POSIX), puis les fonctions, puis les fonctions intégrées, puis une recherche dans $PATH.

Pour exécuter une fonction intégrée, utilisez builtin test.
Pour exécuter une application externe, utilisez un chemin d' accès explicite: /bin/test.
Pour ignorer les fonctions et les alias, utilisez command test.
Pour contourner uniquement l'alias, l'utilisation \testou tout autre type d'extension.

Il est possible de désactiver / activer une fonction intégrée avec enable test.

(Mis à jour selon les commentaires ci-dessous)
(Correction d'une modification d'administration incorrecte que bash a disableintégrée - en fait, il n'y en a que enable)

gena2x
la source
1
@ 1_CR gena2x a raison. Ma réponse a omis des fonctions intégrées spéciales, qui ont priorité sur les fonctions selon POSIX (bien que certains shells ne soient pas conformes; bash ne se conforme qu'en mode POSIX).
Gilles 'SO- arrête d'être méchant'
1
Modification suggérée: les alias sont désactivés lorsque vous citez la commande (ou une partie de celle-ci), comme dans \testou 'test'ou tes't'.
John Kugelman
2
Ce n'est pas une image complète. Semble tout type d'expansion (dans le manuel bash, toute la substitution, l'expansion tilde et ainsi de suite appelé expansion ) désactive les alias. J'ai essayé.
gena2x
1
Citation de la page de manuel bash:.. « Le premier mot de chaque commande simple, si unquoted, est vérifié pour voir si elle a un alias Si oui, ce mot est remplacé par le texte de l'alias Les personnages /, $, backtick et =et aucun des métacaractères du shell ou des guillemets répertoriés ci-dessus peut ne pas apparaître dans un nom d'alias. "
John Kugelman
2
+1 pour savoir comment m'aider à trouver la source de ces informations: il se trouve dans la page de manuel bash, sous la section EXÉCUTION DE LA COMMANDE, deuxième et troisième paragraphes.
twan163
6

Les commandes intégrées sont toujours préférées aux commandes externes. La raison en est que la commande intégrée est plus rapide (et dans certains cas, comme cdou , seule la commande intégrée peut avoir l'effet souhaité).test -o BASH_OPTION

Parfois, la commande externe peut avoir des capacités que le shell intégré ne possède pas. Dans ce cas, vous pouvez appeler la commande externe en donnant un chemin explicite (c'est-à-dire contenant une barre oblique) (cela contourne toute préoccupation concernant l'ordre dans $PATH). Si vous ne voulez pas coder en dur le chemin externe mais que vous voulez empêcher l'utilisation de la fonction intégrée, vous pouvez utiliser "$(type -P test)"(majuscule de note P) en bash, "$(whence -p test)"en ksh et =testen zsh. Une autre façon de forcer l'utilisation d'une commande externe est d'utiliser le commandbuiltin ( command -p test …) ou de passer par l' envutilitaire ( env test …).

Dans zsh, vous pouvez désactiver une fonction intégrée avec disable test. Ceci est permanent (pour le shell ou le sous-shell actuel) jusqu'à ce que la fonction intégrée soit réactivée avec enable test. En bash, vous pouvez faire de même avec enable -n testpour désactiver et enable testréactiver.

Vous pouvez utiliser un alias ou une fonction pour forcer l'exécution d'une commande différente, par exemple alias test=/usr/bin/testou test () { /usr/bin/test "$@"; }. Si vous avez un tel alias, vous pouvez empêcher son utilisation en en citant n'importe quelle partie, par exemple \testexécutera la fonction normale / recherche intégrée / externe. Notez que selon le shell et ses paramètres, les définitions d'alias dans une fonction peuvent être développées lorsqu'une fonction est lue ou lorsqu'elle est exécutée. Si vous avez défini une fonction, vous pouvez utiliser command testpour empêcher la recherche de fonction ainsi que la recherche d'alias (donc ici, la fonction testintégrée sera invoquée sauf si elle est désactivée).

Gilles 'SO- arrête d'être méchant'
la source
ne envserait pas approprié ici aussi?
Steven Penny
donc, si le shell s'exécute à partir de BusyBox, les autres commandes, généralement externes du même BusyBox, sont-elles considérées comme internes? Par exemple, j'ai ajouté dfun chemin complet à la première position, supprimé l'alias 'df', which dfaffiche / opt / bin / df, mais df exécute / bin / df -> busybox
papo
@papo which dfne vous montre pas nécessairement ce qui dffonctionne. unix.stackexchange.com/questions/85249/…
Gilles 'SO- arrête d'être méchant'