Warum muss ich ". /" Eingeben, bevor ich ein Programm im aktuellen Verzeichnis ausführen kann?

92

a.outWarum muss ich beim Ausführen eines C-Programms mit dem Ubuntu-Terminal immer ./vorher tippen a.out, anstatt nur zu schreiben a.out? Gibt es dafür eine Lösung?

Prashant Chikhalkar
quelle

Antworten:

119

Wenn Sie den Namen eines Programms wie Typ - a.outSystem sucht nach der Datei in Ihrer PATH. In meinem System ist PATH auf eingestellt

/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Ihre ist wahrscheinlich ähnlich. Zum Überprüfen geben Sie echo $PATHein Terminal ein.

Das System durchsucht diese Verzeichnisse in der angegebenen Reihenfolge und wenn es das Programm nicht findet, wird ein command not foundFehler ausgegeben .

Wenn Sie dem Befehl ./effektiv den Zusatz "Vergiss den Pfad, ich möchte, dass du nur in das aktuelle Verzeichnis schaust" voranstellen .

Auf ähnliche Weise können Sie das System anweisen, nur an einer anderen bestimmten Stelle zu suchen, indem Sie dem Befehl einen relativen oder absoluten Pfad voranstellen, z.

../bedeutet im übergeordneten Verzeichnis zB ../helloHallo im übergeordneten Verzeichnis suchen.

./Debug/hello: "suche helloim Debug - Unterverzeichnis meines aktuellen Verzeichnisses."

oder /bin/ls: " lsim Verzeichnis suchen /bin"

Standardmäßig befindet sich das aktuelle Verzeichnis nicht im Pfad, da dies als Sicherheitsrisiko angesehen wird. Siehe Warum ist. Nicht im Pfad standardmäßig? auf Superuser für warum.

Es ist möglich, das aktuelle Verzeichnis zu Ihrem PFAD hinzuzufügen, aber aus den in der verknüpften Frage angegebenen Gründen würde ich es nicht empfehlen.

Warren Hill
quelle
25
Diese. +1 Wegen des in dieser Antwort erwähnten Sicherheitsrisikos sollten Sie nicht. zu Ihren PATH(wie in den anderen 2 Antworten vorgeschlagen) hinzufügen .
Tag
8
Es kann auch sinnvoll sein Hinweis darauf , dass es nichts Besonderes ist .hier, Sie einen vollständigen oder relativen Pfad zu einer ausführbaren zB verwenden können , /home/user/foo/a.outoder./build/a.out
tobyodavies
@tobyodavies; Eigentlich .ist es etwas Besonderes, denn es bedeutet "Mein aktuelles Verzeichnis" und kann jedes Verzeichnis sein, in dem sich der Benutzer mit Lese- und Ausführungsrechten befindet. Dies ist möglicherweise gefährlicher als das Hinzufügen eines bestimmten vollständig qualifizierten Pfads.
Warren Hill
@WarrenHill Wenn Sie darüber nachdenken, es zu Ihrem Pfad hinzuzufügen, ist es ja ganz anders. Jedoch in Bezug auf der bash - Syntax, .hält keinen besonderen Status, es ist nur ein Weg, der mit genauso gut beginnen könnte /und ./blahwürde genauso gut mit arbeiten catoder grepals Bash - Eingabeaufforderung.
Tobyodavies
@tobyodavies: OK, ich habe meine Antwort so bearbeitet, dass sie Ihren Punkt enthält.
Warren Hill
24

Der Grund dafür ist einfach.

Angenommen, Sie haben einen Befehl mit demselben Namen wie eine Anwendung im aktuellen Verzeichnis. Wenn Sie den Befehl dann in der Shell ausführen, wird Ihre App anstelle des integrierten Befehls aufgerufen. Dies wäre ein Sicherheitsrisiko, wenn nichts anderes.

Da ./die Shell vorausgesetzt wird, dass sie im Vordergrund verwendet wird, weiß sie, dass Sie die Anwendung mit dem angegebenen Namen ausführen möchten und nicht mit einem integrierten Befehl mit diesem Namen.

Nathan Osman
quelle
1
Ihre Erklärung ist irreführend. Es gibt einen Unterschied zwischen integrierten Befehlen in einer Shell und ausführbaren Dateien, auf die über die Variable PATH zugegriffen werden kann. Tatsächlich fühlt sich Ihre Antwort umso falscher an, je mehr ich sie lese.
Ahmed Masud
16

./führt Dateien aus, die sich nicht in Ihrem befinden $PATH, sondern führt die Datei im aktuellen Verzeichnis (oder einem anderen Via ./home/stefano/script.sh) aus. Jetzt ist PATH eine Umgebungsvariable, die alle Stellen enthält, an denen bash nach ausführbaren Programmen suchen kann, ohne den vollständigen (absoluten) Pfad zu ihnen zu haben.

Diese Trennung ist erforderlich, um zu vermeiden, dass die falsche Datei ausgeführt wird. Wenn Sie also eine Datei lsin Ihrem Home-Verzeichnis haben, die nicht in Ihrem PATH enthalten ist, kann bash sie nicht mit der echten verwechseln ls. Die Variable PATH definiert auch die Suchreihenfolge:

  • Wenn Sie einen Befehl ausführen oder ein Programm versucht, einen execSystemaufruf durchzuführen (eine spezielle Methode des Kernels, wie Programme gestartet werden), sucht das System nach der Datei, indem es alle Verzeichnisse in Ihrem PATH durchsucht. Sobald das Programm gefunden wurde, wird die Suche unterbrochen, auch wenn es sich in mehreren Verzeichnissen befindet, und das erste gefundene Programm wird ausgeführt.

Um eine Datei auszuführen, müssen Sie das ausführbare Bit in den Berechtigungen festlegen:

  • Da Sie bereits in der Befehlszeile sind, können Sie einfach eingeben chmod +x finename.

  • Sie können die Berechtigungen auch festlegen, indem Sie mit der rechten Maustaste auf die Datei klicken und Eigenschaften auswählen :

    Alt-Text

Sie können die Datei jetzt in eines der Verzeichnisse in PATH kopieren, um zu sehen, welche Verzeichnisse sich dort befinden - und welche benutzerspezifisch festgelegt sind - echo $PATH.

stefano@3000-G530:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Wenn Sie eine ausführbare Datei erstellen catund in diese verschieben, /usr/local/sbinwird diese anstelle der eigentlichen Datei ausgeführt, in der sich die Datei catbefindet /bin. Sie können herausfinden, wo Ihre Dateien sind durch die Verwendung type catund whereis cat.

Stefano Palazzo
quelle
2
Eines ist zu beachten: Seine Frage scheint darauf hinzudeuten, dass er etwas kompiliert und verknüpft hat gcc, wodurch das Ausführungsbit automatisch gesetzt wird.
Nathan Osman
12

Warum müssen Sie ./vor dem Ausführen eines Programms etwas eingeben?

Wenn Sie im Terminal den Namen einer Anwendung eingeben, durchsucht geditdas Terminal beispielsweise einige (vordefinierte) Verzeichnisse, die Anwendungen enthalten (die Binärdateien der Anwendungen). Die Namen dieser Verzeichnisse sind in einer Variablen namens enthalten PATH. Sie können sehen, was in dieser Variablen enthalten ist, indem Sie ausführen echo $PATH. Sehen Sie diese Verzeichnisse getrennt durch :? Das sind die Verzeichnisse , die das Terminal gehen sucht in, wenn Sie nur geben gedit, nautilusoder a.out. Wie Sie sehen, ist der Pfad Ihres a.outProgramms nicht vorhanden. Wenn Sie dies tun ./a.out, teilen Sie dem Terminal mit, dass Sie in das aktuelle Verzeichnis schauen und ausführen a.outund nicht hineingehen PATH.

Lösung 1

Wenn Sie nicht ./jedes Mal etwas eingeben möchten , müssen Sie das a.outVerzeichnis hinzufügen $PATH. In den folgenden Anweisungen gehe ich davon aus, dass der Pfad zu a.outlautet /path/to/programs/, Sie sollten ihn jedoch in Ihren tatsächlichen Pfad ändern.

  1. Fügen Sie einfach die folgende Zeile am Ende der Datei hinzu ~/.pam_environment:

    PATH DEFAULT=${PATH}:/path/to/programs

    Quelle: Persistente Umgebungsvariablen

  2. Melden Sie sich ab und wieder an. Sie können jetzt a.outohne ./Verzeichnis ausgeführt werden.

Wenn Sie andere Programme in anderen Verzeichnissen haben, können Sie diese einfach in die obige Zeile einfügen. Ich würde jedoch empfehlen, ein Verzeichnis mit dem Namen "myPrograms" zu haben und alle Ihre Programme darunter abzulegen.

Lösung 2

Hinweis: Wechseln Sie userNamezu Ihrem tatsächlichen Ubuntu-Benutzernamen.

Was ist, wenn Sie andere Programme haben, die Sie ausführen möchten? Und sie sind alle in verschiedenen Ordnern? Nun, eine "besser organisierte" Lösung wäre, einen Ordner binunter Ihrem Home-Verzeichnis zu erstellen und symbolische Links (Verknüpfungen) unter diesem Ordner hinzuzufügen. Hier ist wie:

  1. mkdir /home/userName/bin

    • Dadurch wird der Ordner binunter Ihrem Home-Verzeichnis erstellt.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Dies wird eine "symbolische Verknüpfung" (im Grunde genommen eine Verknüpfung) Ihres a.outProgramms unter erstellen bin.
  3. Melden Sie sich ab und wieder an. Sie können jetzt a.outohne ./Verzeichnis ausgeführt werden.

Wenn Sie jetzt irgendwo anders ein anderes Programm haben, sagen wir, das Programm b.inauf Ihrem Desktop, müssen Sie nur noch Folgendes tun ln -s /home/userName/Desktop/b.in /home/userName/bin:, und Sie können es dann auch ohne ausführen ./.

Hinweis: Dank des Kommentars von @ Joe müssen symbolische Links bei Backups besonders behandelt werden. Standardmäßig werden sie rsyncüberhaupt nicht verarbeitet. Wenn Sie also wiederherstellen, sind sie nicht vorhanden.

Alaa Ali
quelle
1
Dies ist ein praktischer Trick, wenn er sparsam eingesetzt wird. Wenn Sie es häufig verwenden, erledigt Ihr System Dinge, die jemand anderes nicht erwartet. Außerdem müssen bei Backups Symlinks speziell behandelt werden. Standardmäßig verarbeitet rsync sie überhaupt nicht. Wenn Sie also wiederherstellen, sind sie nicht vorhanden.
Joe
1

Wie George in seiner Antwort betont hat, können Sie dadurch feststellen, dass Sie eine Datei im aktuellen Arbeitsverzeichnis ausführen ( pwd).

Ich erinnere mich, dass ich diese Frage vor langer Zeit an meinen Senior gestellt habe. Er sagte, ich solle .meinen Pfad erweitern, damit er beim a.outAusführen im aktuellen Verzeichnis nachschaut und das ausführt. In diesem Fall muss ich nicht tun ./a.out.

Aber persönlich würde ich dagegen empfehlen. Das ist mir noch nie passiert, aber wenn Sie sich in einem fremden Netzwerkverzeichnis oder so befinden und dort eine böswillige ausführbare Datei mit dem Namen lsexistiert, .ist es eine sehr schlechte Idee , in Ihrem Pfad zu sein. Nicht, dass Sie sehr oft auf dieses Problem stoßen, wenn Sie nur sagen.

Shrikant Sharat
quelle
ok, Stefano hat seine Antwort angenommen, um diese Information zu enthalten :)
Shrikant Sharat
3
Ich stimme dem nicht .zu $PATH. Sehr gefährliche Idee.
Nathan Osman
1

Neben anderen Antworten hier der wesentliche Teil, aus man bashdem das gut hervorgeht:

BEFEHLSAUSFÜHRUNG
       Nachdem ein Befehl in Wörter aufgeteilt wurde, ergibt sich ein einfacher
       Befehl und eine optionale Liste von Argumenten sind die folgenden Aktionen
       genommen.

       Wenn der Befehlsname keine Schrägstriche enthält, versucht die Shell zu suchen
       es. Wenn es eine Shell-Funktion mit diesem Namen gibt, ist diese Funktion
       wird wie oben in FUNCTIONS beschrieben aufgerufen. Wenn der Name nicht mit a übereinstimmt
       Funktion sucht die Shell danach in der Liste der eingebauten Shell. Wenn
       Wird eine Übereinstimmung gefunden, wird das Builtin aufgerufen.

       Wenn der Name weder eine Shell-Funktion noch eine eingebaute Funktion ist und no enthält
       Schrägstriche, Bash durchsucht jedes Element des PATH nach einem Verzeichnis, das
       Beibehalten einer ausführbaren Datei mit diesem Namen.
mook765
quelle
0

Ein './' ist sinnvoll, wenn Sie ein für Sie bekanntes und spezifisches Programm ausführen, z. B. Ihr eigenes. Dieses Programm muss in Ihrem aktuellen Verzeichnis vorhanden sein. Ein './' macht keinen Sinn, wenn Sie einen Standardbefehl ausführen, der sich irgendwo im $ PATH befindet. Ein Befehl "welcher Befehl ausgeführt werden soll" gibt an, wo sich der auszuführende Befehl im $ PATH befindet.

user7346
quelle
0
$ gcc hello.c -o /path/to/someplace/hello

wird eine ausführbare Datei an einem Ort produzieren. Befindet sich dieser Speicherort in Ihrem Pfad, können Sie die Datei ausführen. Sie können dies skripten, wenn Sie eine Bezeichnung für die Aktion "Kompilieren Sie diesen Quellcode mit dem gcc und platzieren Sie eine ausführbare Datei an einem Ort, der sich auf Ihrem Pfad befindet" erstellen möchten.

Ich würde vorschlagen, dass Sie ein neues Verzeichnis mit dem Namen "testbin" oder etwas in dieser Art erstellen und es in Ihren Pfad einfügen, um Ihre vorhandenen Pfadverzeichnisse sauber zu halten.

Jon Kiparsky
quelle
0

./eliminiert die unnötige Suche nach einem Pfad. ./zwingen, nur im aktuellen Verzeichnis zu suchen. Wenn wir nicht angeben ./, wird nach verschiedenen Pfaden gesucht, die in das System eingegeben /usr/binwurden /usr/sbin/, wie z .

user175959
quelle
0

"./" bedeutet, dass Sie eine Datei im aktuellen Verzeichnis ausführen möchten. Dies ist eine Abkürzung, mit der Sie den gesamten Pfad eingeben können. Beispiel:

[root@server ~]#/path/to/file/file.pl

ist dasselbe wie:

[root@server file]#./file.pl

Im vorherigen Beispiel haben Sie das Verzeichnis und seine Unterverzeichnisse zum Speicherort der Datei durchsucht und "./" verwendet, um die Datei im aktuellen Verzeichnis auszuführen.

Der davor stehende Befehl " [root @ server ~] # / path / to / file / file.pl " führt die Datei ebenfalls aus, wenn Sie nur faul sind, den Weg zum Dateispeicherort zu " cden ".

Khaled Moustafa
quelle
-4

Es ist sehr einfach und vielseitig einsetzbar.

  1. Wenn mehrere Versionen der gleichen Anwendung installiert sind, ist diese in unterschiedlichen Pfaden verfügbar, es kann jedoch ein Softlink zu Ihrer Binärdatei in erstellt werden /usr/bin. Zum Beispiel ist Python 2.7, Python 2.6 installiert, aber / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Wenn Sie sich im Pfad befinden /usr/local/binund Python ausführen, wird immer Python 2.7 ausgeführt. Die Angabe .übernimmt die ausführbare Datei des aktuellen Ordners.

  1. .- Stellt immer die Ausführung aus dem aktuellen Verzeichnis dar. Und ..bedeutet immer führt aus dem vorherigen Verzeichnis.
Ramjee Anna
quelle