Die Reihenfolge der ausführbaren Dateien wurde in bash gestartet

14

Wenn ich den testBefehl in bash ausführe, wird das testintegrierte Dienstprogramm gestartet (wertet den bedingten Ausdruck aus):

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

Wie in der type -a testobigen Ausgabe zu sehen ist , gibt es jedoch ein weiteres testVerzeichnis im Verzeichnis / usr / local / bin und ein weiteres im Verzeichnis / usr / bin. Wie werden ausführbare Dateien sortiert, dh werden die integrierten Befehle immer bevorzugt, und der Rest der Befehle hängt von der Verzeichnisreihenfolge in der Variablen $ PATH ab? Ist es außerdem möglich, die Reihenfolge der gestarteten ausführbaren Dateien zu ändern, z. B. wenn ich testtippe, wird / usr / bin / test anstelle von bash-builtin gestartet test?

Martin
quelle
Sie können den vollständigen Pfad angeben, wenn Sie den Befehl aufrufen, z. B. /usr/bin/test -f "$file"...
jasonwryan
@jasonwryan Ich bin mir dessen bewusst, aber ich bin nur interessiert, ob es eine Möglichkeit gibt, die Reihenfolge der gestarteten ausführbaren Dateien zu ändern.
Martin

Antworten:

25

Die höchste Priorität ist der Bash-Alias, dann spezielle integrierte Funktionen (nur im POSIX-Modus), dann Funktionen, dann integrierte Funktionen und dann eine Suche $PATH.

Verwenden Sie zum Ausführen eines integrierten Geräts builtin test.
Verwenden Sie zum Ausführen einer externen Anwendung einen expliziten Pfad : /bin/test.
Verwenden Sie, um Funktionen und Aliase zu ignorieren command test.
Um nur Alias ​​zu umgehen, verwenden Sie \testoder eine andere Art von Erweiterung.

Es ist möglich, ein eingebautes System mit zu deaktivieren / aktivieren enable test.

(Aktualisiert gemäß den Kommentaren unten)
(Fehlerhafte falsche Administrator-Bearbeitung disablebehoben , die bash eingebaut hat - tatsächlich gibt es nur enable)

gena2x
quelle
1
@ 1_CR gena2x ist richtig. In meiner Antwort wurden spezielle integrierte Funktionen weggelassen, die Vorrang vor Funktionen gemäß POSIX haben (obwohl einige Shells nicht kompatibel sind; bash entspricht nur im POSIX-Modus).
Gilles 'SO - hör auf böse zu sein'
1
Vorgeschlagene Bearbeitung: Aliase werden deaktiviert, wenn Sie den Befehl (oder einen Teil davon) wie in \testoder 'test'oder zitieren tes't'.
John Kugelman
2
Das ist kein vollständiges Bild. Es scheint, dass jede Art von Erweiterung (im Bash-Handbuch alle Substitutionen, Tilde-Erweiterungen usw., sogenannte Erweiterungen ) Aliase deaktiviert. Ich habe es versucht.
Gena2x
1
Zitat aus der bash man - Seite:.. „Das erste Wort eines jeden einfachen Befehls, wenn nicht notiert, geprüft, um zu sehen , ob es einen Alias hat Wenn ja, dieses Wort durch den Text des Alias ersetzt Die Zeichen /, $, Graviszeichen und =und eines der oben aufgeführten Shell-Metazeichen oder Anführungszeichen wird möglicherweise nicht in einem Aliasnamen angezeigt. "
John Kugelman
2
+1 für Hinweise, die mir helfen, die Quelle dieser Informationen zu finden: Sie finden sie in der Bash-Manpage im Abschnitt BEFEHLSAUSFÜHRUNG, zweiter und dritter Absatz.
Twan163
6

Integrierte Befehle werden immer externen Befehlen vorgezogen. Das Grundprinzip ist, dass der eingebaute Befehl schneller ist (und in einigen Fällen, wie z. B. cdoder , nur der eingebaute Befehl den gewünschten Effekt haben kann).test -o BASH_OPTION

Manchmal verfügt der externe Befehl über Funktionen, die die integrierte Shell nicht bietet. In diesem Fall können Sie den externen Befehl aufrufen, indem Sie einen expliziten Pfad angeben (dh einen Schrägstrich enthalten) (dies umgeht alle Bedenken hinsichtlich der Reihenfolge in $PATH). Wenn Sie den externen Pfad nicht fest codieren möchten, aber die Verwendung des integrierten Pfads verhindern möchten, können Sie "$(type -P test)"( Notizkapital P) in bash, "$(whence -p test)"in ksh und =testin zsh verwenden. Eine andere Möglichkeit, die Verwendung eines externen Befehls zu erzwingen, besteht darin, das commandeingebaute ( command -p test …) zu verwenden oder das envDienstprogramm ( env test …) zu durchlaufen .

In zsh können Sie ein eingebautes System mit deaktivieren disable test. Dies ist permanent (für die aktuelle Shell oder Subshell), bis das eingebaute System wieder aktiviert wird enable test. In bash können Sie dasselbe tun enable -n test, um zu deaktivieren und wieder enable testzu aktivieren.

Sie können einen Alias ​​oder eine Funktion verwenden, um die Ausführung eines anderen Befehls zu erzwingen, z. B. alias test=/usr/bin/testoder test () { /usr/bin/test "$@"; }. Wenn Sie über einen solchen Alias ​​verfügen, können Sie dessen Verwendung verhindern, indem Sie einen Teil davon zitieren, z. B. \testdie normale Funktion / integrierte / externe Suche ausführen. Beachten Sie, dass Aliasdefinitionen in einer Funktion abhängig von der Shell und ihren Einstellungen erweitert werden können, wenn eine Funktion gelesen oder ausgeführt wird. Wenn Sie eine Funktion definiert haben, können Sie damit sowohl command testdie Funktionssuche als auch die testAliasuche verhindern (daher wird hier die integrierte Funktion aufgerufen, sofern sie nicht deaktiviert ist).

Gilles 'SO - hör auf böse zu sein'
quelle
wäre envauch hier nicht angebracht?
Steven Penny
Wenn die Shell von BusyBox ausgeführt wird, werden andere, normalerweise externe Befehle von derselben BusyBox als intern betrachtet? zB habe ich dfeinen PATH an der ersten Position voll hinzugefügt , den Alias ​​'df' entfernt, which dfzeigt / opt / bin / df, aber df läuft / bin / df -> Busybox
Papo
@papo which dfzeigt Ihnen nicht unbedingt, was dfläuft. unix.stackexchange.com/questions/85249/…
Gilles 'SO- hör auf böse zu sein'