Ich habe ein einfaches C-Programm wie folgt erstellt:
int main(int argc, char *argv[]) {
if (argc != 5) {
fputs("Not enough arguments!\n", stderr);
exit(EXIT_FAILURE);
}
Und ich habe meinen PATH in etc / bash.bashrc wie folgt geändert :
PATH=.:$PATH
Ich habe dieses Programm als set.c gespeichert und kompiliere es mit
gcc -o set set.c
im Ordner
~/Programming/so
Wenn ich jedoch anrufe
set 2 3
nichts passiert. Es wird kein Text angezeigt.
Berufung
./set 2 3
gibt das erwartete Ergebnis
Ich hatte noch nie ein Problem mit PATH und
which set
kehrt zurück ./set
. Es scheint also, dass der PFAD der richtige ist. Was ist los?
shell
path
shell-builtin
Ganea Dan Andrei
quelle
quelle
test
aus dem gleichen Grund aufzurufen .test
ist auch eine Shell eingebaut.test
scheint es für schnelle Tests sinnvoll , ein Programm aufzurufen . Natürlich sollten Sie sich zu dem Zeitpunkt, an dem Sie es in IhrPATH
Telefon einfügen, einen anderen Namen einfallen lassen. Und bis Sie das Programm in Ihr ProgrammPATH
eingefügt haben, müssen Sie es./test
trotzdem aufrufen . Es ist also in Ordnung, den Namentest
für ein Programm zu verwenden, solange es sich um einen Schnelltest handelt, den Sie vor Tagesende löschen möchten.foo
.ls
dann benennen, wird es ausgeführt, wenn Sie nachsehen, ob es vorhanden ist (jedoch nur, wenn Sie Ihren Pfad wie in der Frage beschrieben ändern).Antworten:
Anstatt zu verwenden
which
, was nicht funktioniert, wenn Sie es am meisten benötigen ,type
bestimmen Sie mit, was ausgeführt wird, wenn Sie einen Befehl eingeben:Die Shell sucht vor dem Durchsuchen immer nach eingebauten Elementen
$PATH
, daher$PATH
hilft die Einstellung hier nicht weiter.Es ist am besten, Ihre ausführbare Datei in etwas anderes umzubenennen. Wenn für Ihre Zuweisung jedoch der Name des Programms erforderlich ist
set
, können Sie eine Shell-Funktion verwenden:(Das funktioniert in
bash
, aber andere Shells wieksh
erlauben es möglicherweise nicht. Siehe mikeservs Antwort für eine tragbarere Lösung.)Durch die Eingabe
set
wird nun die Funktion "set" ausgeführt, die ausgeführt wird./set
. GNUbash
sucht nach Funktionen, bevor es nach Builtins sucht, und es sucht nach Builtins, bevor es nach$PATH
. Weitere Informationen hierzu finden Sie im Abschnitt "BEFEHLSAUSFÜHRUNG" in der Bash-Manpage.Siehe auch die Dokumentation zu
builtin
undcommand
:help builtin
undhelp command
.quelle
type
überwhich
, geben aber keinen Grund an, warum. ( Ich weiß warum , aber jemand, der die Empfehlung braucht, würde nicht.)type
stattwhich
, nennen Sie Ihr Programm nicht "set" und stellen Sie fest, dass diesfunction set { ./set; }
ein hässlicher Hack ist, den Sie wahrscheinlich vermeiden sollten.set
ist eine eingebaute Bash (und wahrscheinlich die meisten anderen Muscheln). Dies bedeutet, dass bash bei der Suche nach der Funktion nicht einmal den Pfad durchsucht.Als Randbemerkung würde ich
.
aus Sicherheitsgründen dringend davon abraten , den Pfad zu erweitern. Stellen Sie sich zum Beispiel vorcd
,/tmp
nachdem ein anderer Benutzer eine ausführbare Datei hinzugefügt hat/tmp/cd
.quelle
cd
ist eine integrierte Shell, daher funktioniert das Beispiel aus dem gleichen Grund nicht wie mitset
../foo
Aufrufen eines Programms ist professionell. Es zeigt, dass Sie verstehen, warum.
nicht in $ PATH sein sollte. Ihr Lehrer liegt falsch, und Sie können ihm sagen, dass ich es gesagt habe.set
ist nicht nur ein eingebautes, es ist ein POSIX-Spezial eingebaut . Es gibt einige eingebaute Befehle, die standardmäßig spezifiziert sind, um in einer Befehlssuche vor allem anderen gefunden zu werden -$PATH
werden nicht durchsucht, Funktionsnamen werden nicht durchsucht usw. Die meisten eingebauten Befehle, die nicht speziell sind, werden vom POSIX-Standard tatsächlich benötigt gefunden in Ihrem,$PATH
bevor die Shell eine ihrer eigenen eingebauten Prozeduren ausführt. Dies gilt fürecho
und die meisten anderen (obwohl , ob der Standard in dieser Hinsicht ausgezeichnet , hat in der Vergangenheit strittig an den offenen Gruppe Mailinglisten) , aber nicht vonset
,trap
,break
,return
,continue
,.
,:
,times
,eval
,exit
,export
,readonly
,unset
, Oderexec
.All dies sind reservierte Namen der Shell, und sie haben andere spezielle Attribute als ihre bevorzugte Reihenfolge für die Befehlssuche. Beispielsweise können Sie in einer standardkonformen Shell keine Shell-Funktion mit einem dieser Namen definieren. Dies ist eine gute Sache - es ermöglicht Menschen, tragbare Skripte sicher zu schreiben . Dies sind Basisbefehle, mit denen ein erfahrener Drehbuchautor einen sicheren und zuverlässigen Halt in seiner Umgebung finden kann. Das Eindringen in diesen Namespace ist nicht ratsam.
Wenn Sie jedoch in das Gebiet eindringen möchten, können Sie dies portabel mit tun
alias
. Die Reihenfolge der Shell- Erweiterung ermöglicht diese Umgehung. Da dasalias
erweitert wird, während der Befehl gelesen wird, wird alles, durch das Sie denset
Namen in Ihrer Definition ersetzen , korrekt erweitert. Es sollte nur wahrscheinlich nicht auf einen dieser Namen erweitert werden.So könnten Sie tun:
... was gut funktionieren wird.
quelle
Das Problem ist, dass
set
eine Shell eingebaut ist und die beste Lösung darin besteht, einen anderen Namen für Ihr ausführbares Programm zu verwenden.Übrigens habe ich letzte Woche eine Frage gestellt, wie Systembefehle anstelle von Shell-Builds mit demselben Namen ausgeführt werden sollen. Die Lösung, die ich akzeptiert habe, bestand darin, den Befehl auszuführen
env
:In diesem speziellen Fall, in dem Sie bereits wissen, dass sich der zu verwendende Befehl in Ihrem aktuellen Verzeichnis befindet, ist es besser, die ausführbare Datei direkt auszuführen, indem Sie ihren Pfad eingeben (
.
um das aktuelle Arbeitsverzeichnis darzustellen):Beide oben genannten Lösungen sind Shell-unabhängig, dh sie funktionieren unabhängig davon, welche Shell Sie verwenden.
Vorschläge wie die Verwendung des integrierten
command
Systems funktionieren in Bash nicht: Dies verhindert nur, dass Shell- Funktionen ausgeführt werden. Es ist zwar nicht dokumentiert, aber ich habe auch festgestellt, dass die Verwendungcommand
auch Shell- Schlüsselwörter unterdrückt . Bei Shell- Builds wie zset
. Soweit ich weiß,command
kann mit anderen Shells wie zsh arbeiten.Auch Tricks wie
\set
oder"set"
oder'set'
nicht Arbeit für Bash builtins - obwohl sie für die Ausführung von ausführbaren Dateien statt nützlich sind Aliase oder Shell - Schlüsselwörter .Hinweis: Diese Antwort begann ursprünglich als Kommentar zu Erics (akzeptierter) Antwort, wurde jedoch zu groß, um in einen Kommentar zu passen. Die anderen Antworten, die die Verwendung des PATH empfehlen
type
und ihn nicht.
ergänzen, sind gut.quelle