Pourquoi dois-je taper `. /` Avant d'exécuter un programme dans le répertoire en cours?

92

Lors de l'exécution d'un programme C a.out, à l'aide du terminal Ubuntu, pourquoi dois-je toujours taper ./avant a.out, au lieu d'écrire a.out? Y a-t-il une solution pour cela?

Prashant Chikhalkar
la source
Related Q sur Unix.SE Pourquoi
Ivan Chau
Le canonique: unix.stackexchange.com/q/4430/89884
Pacerier

Réponses:

119

Lorsque vous tapez le nom d'un programme tel que a.outle système cherche le fichier dans votre PATH. Sur mon système, PATH est défini sur

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

Le vôtre est probablement similaire. Pour vérifier, entrez echo $PATHdans un terminal.

Le système examine ces répertoires dans l'ordre indiqué et, s'il ne trouve pas, le programme génère une command not founderreur.

Le préfixe de la commande ./indique effectivement "oubliez PATH, je veux que vous regardiez uniquement dans le répertoire en cours".

De la même manière, vous pouvez demander au système de rechercher uniquement un autre emplacement spécifique en ajoutant à la commande un préfixe relatif ou absolu, tel que:

../signifie dans le répertoire parent, par exemple, ../hellorecherchez hello dans le répertoire parent.

./Debug/hello: "cherche hellodans le sous-répertoire Debug de mon répertoire actuel."

ou /bin/ls: "chercher lsdans le répertoire /bin"

Par défaut, le répertoire en cours ne se trouve pas dans le chemin car il est considéré comme un risque pour la sécurité. Voir pourquoi est. pas dans le chemin par défaut? sur superutilisateur pour pourquoi.

Il est possible d'ajouter le répertoire actuel à votre PATH, mais pour les raisons données dans la question liée, je ne le recommanderais pas.

Warren Hill
la source
25
Cette. +1 Ne pas ajouter .à votre PATH(comme les 2 autres réponses suggèrent actuellement) en raison du risque de sécurité mentionné dans cette réponse.
Jour
8
Il peut également être intéressant de noter qu'il n'y a rien spécial .ici, vous pouvez utiliser un chemin complet ou par rapport à un exemple exécutable /home/user/foo/a.outou./build/a.out
tobyodavies
@tobyodavies; En fait, .c’est spécial parce que cela signifie "mon répertoire actuel", ainsi que tout répertoire dans lequel l’utilisateur se trouve lui-même avec les privilèges de lecture et d’exécution. Ceci est potentiellement plus dangereux que l’ajout d’un chemin qualifié complet.
Warren Hill
@WarrenHill lorsque vous envisagez de l'ajouter à votre chemin, oui, c'est tout à fait différent. Cependant , en termes de syntaxe bash, .détient pas un statut particulier, il est juste un chemin qui pourrait tout aussi bien commencer /et ./blahfonctionnerait aussi bien avec catou grepcomme une invite bash.
tobyodavies
@tobyodavies: OK, j'ai modifié ma réponse pour inclure votre point.
Warren Hill
24

La raison en est simple.

Supposons que vous ayez une commande portant le même nom qu'une application dans le répertoire en cours. Ensuite, exécuter la commande dans le shell invoquerait votre application au lieu de la commande intégrée. Ce serait un problème de sécurité si rien d’autre.

En demandant ./à être utilisé devant, le shell sait que vous souhaitez exécuter l'application avec le nom indiqué et non avec une commande intégrée portant ce nom.

Nathan Osman
la source
1
votre explication est trompeuse, il y a une différence entre les commandes intégrées dans un shell et les exécutables accessibles via la variable PATH. En fait, votre réponse, plus je lis, c’est plus inexacte.
Ahmed Masud
16

./exécute des fichiers qui ne sont pas dans votre $PATHfichier, mais exécute plutôt le fichier dans le répertoire actuel (ou un autre via ./home/stefano/script.sh). Maintenant, PATH est une variable d’environnement qui contient tous les endroits où bash peut rechercher des programmes exécutables sans avoir le chemin complet (absolu).

Cette séparation est nécessaire pour éviter d’exécuter le mauvais fichier. C'est-à-dire que si vous avez un fichier appelé lsdans votre répertoire personnel, le fait qu'il ne soit pas dans votre PATH empêchera bash de le confondre avec le réel ls. La variable PATH définit également l'ordre de recherche:

  • Lorsque vous exécutez une commande ou qu'un programme essaie de lancer un execappel système (méthode spéciale du noyau permettant de démarrer les programmes), le système recherche le fichier en parcourant chacun des répertoires de votre PATH. Une fois le programme trouvé, même s'il se trouve dans plusieurs annuaires, la recherche est interrompue et le premier trouvé est exécuté.

Pour exécuter un fichier, vous devez définir le bit exécutable dans les autorisations:

  • Puisque vous êtes déjà en ligne de commande, vous pouvez simplement taper chmod +x finename.

  • Ou vous pouvez définir les autorisations en faisant un clic droit sur le fichier et en sélectionnant Propriétés :

    texte alternatif

Vous pouvez maintenant copier le fichier dans n’importe quel des répertoires de PATH pour voir quels sont ceux-ci - et ils sont définis par utilisateur - type echo $PATH.

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

Si vous créez un fichier exécutable catet que vous le déplacez /usr/local/sbin, il est exécuté à la place du fichier approprié cat, qui réside dans /bin. Vous pouvez trouver où sont vos fichiers en utilisant type catet whereis cat.

Stefano Palazzo
la source
2
Une chose à noter: sa question semble indiquer qu'il a compilé et lié quelque chose avec gcc, ce qui définit automatiquement le bit d'exécution.
Nathan Osman
12

Pourquoi avez-vous besoin de taper ./avant d'exécuter un programme?

Dans le terminal, chaque fois que vous tapez le nom d'une application, par exemple gedit, le terminal va rechercher des répertoires (prédéfinis) contenant des applications (les fichiers binaires des applications). Les noms de ces répertoires sont contenus dans une variable appelée PATH. Vous pouvez voir le contenu de cette variable en exécutant echo $PATH. Voir ces répertoires séparés par :? Ce sont les répertoires que le terminal aller rechercher, si vous tapez juste gedit, nautilusou a.out. Comme vous pouvez le constater, le chemin de votre a.outprogramme n’est pas là. Lorsque vous le faites ./a.out, vous dites au terminal "regardez dans le répertoire actuel, puis exécutez a.out-le et ne le regardez pas PATH."

Solution 1

Si vous ne voulez pas taper à ./chaque fois, vous devez ajouter a.outle répertoire dans $PATH. Dans les instructions suivantes, je suppose que le chemin d'accès a.outest /path/to/programs/, mais vous devez le changer pour votre chemin réel.

  1. Ajoutez simplement la ligne suivante à la fin du fichier ~/.pam_environment:

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

    Source: variables d'environnement persistantes

  2. Déconnectez-vous et reconnectez-vous. Vous pourrez maintenant exécuter a.outsans ./répertoire.

Si vous avez d'autres programmes dans d'autres répertoires, vous pouvez simplement les ajouter à la ligne ci-dessus. Cependant, je vous conseillerais par exemple d'avoir un répertoire appelé "mes programmes" et de placer tous vos programmes sous celui-ci.

Solution 2

Remarque: remplacez userNamevotre nom d'utilisateur Ubuntu actuel.

Et si vous avez d'autres programmes à exécuter? Et ils sont tous dans des dossiers différents? Une solution "plus organisée" consisterait à créer un dossier appelé binsous votre répertoire de base et à ajouter des liens symboliques (raccourcis) sous ce dossier. Voici comment:

  1. mkdir /home/userName/bin

    • Cela créera le dossier bindans votre répertoire de base.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Cela créera un "lien symbolique" (en gros, un raccourci) de votre a.outprogramme sous bin.
  3. Déconnectez-vous et reconnectez-vous. Vous pourrez maintenant exécuter a.outsans ./répertoire.

Maintenant, chaque fois que vous avez un autre programme n'importe où ailleurs, disons le programme b.insur votre bureau, tout ce que vous avez à faire est:, ln -s /home/userName/Desktop/b.in /home/userName/binet vous pourrez alors l'exécuter sans vous ./aussi.

Remarque: grâce au commentaire de @ Joe , lorsque vous effectuez des sauvegardes, les liens symboliques doivent être traités de manière spécifique. Par défaut, ils rsyncne sont pas traités du tout. Ainsi, lors de la restauration, ils ne sont pas là.

Alaa Ali
la source
1
C'est un truc pratique s'il est utilisé avec parcimonie. Son utilisation fréquente incite votre système à effectuer des tâches inattendues. De plus, lorsque vous effectuez des sauvegardes, les liens symboliques doivent être traités spécialement. Par défaut , rsync ne les traite pas du tout. Par conséquent, lors de la restauration, elles ne sont pas présentes.
Joe
1

Comme George l'a souligné dans sa réponse, cela vous aide à noter que vous exécutez un fichier dans le répertoire de travail actuel ( pwd).

Je me souviens d’avoir posé cette question à mon aîné il y a longtemps, il a dit que je devrais ajouter .à mon chemin afin que, lorsque je le ferais, a.outil regarde dans le répertoire en cours et l’exécute. Dans ce cas je n'ai pas à faire ./a.out.

Mais, personnellement, je le déconseille. Cela ne m'est jamais arrivé, mais si vous êtes sur un répertoire de réseau extraterrestre ou quelque chose du genre, et qu'un fichier exécutable malveillant appelé lsexiste là-bas, alors avoir .dans votre chemin est une très mauvaise idée. Non pas que vous rencontriez ce problème très souvent, simplement en disant.

Shrikant Sharat
la source
ok, Stefano a adopté sa réponse pour contenir cette information :)
Shrikant Sharat
3
Je suis complètement d'accord avec ne pas ajouter .à $PATH. Idée très dangereuse.
Nathan Osman
1

En plus d’autres réponses, voici la partie essentielle de man bashce qui explique bien:

Exécution de commande
       Après qu'une commande ait été scindée en mots, s'il en résulte une simple
       commande et une liste optionnelle d'arguments, les actions suivantes sont
       pris.

       Si le nom de la commande ne contient pas de barre oblique, le shell tente de localiser
       il. S'il existe une fonction shell portant ce nom, cette fonction est
       invoqué comme décrit ci-dessus dans FONCTIONS. Si le nom ne correspond pas à un
       fonction, le shell le recherche dans la liste des commandes intégrées au shell. Si
       une correspondance est trouvée, cette construction est invoquée.

       Si le nom n’est ni une fonction shell, ni une fonction intégrée, et ne contient pas
       slash, bash cherche dans chaque élément du PATH un répertoire contenant
       taining un fichier exécutable de ce nom.
mook765
la source
0

Un './' prend tout son sens lorsque vous exécutez un programme connu pour vous et spécifique, par exemple le vôtre. Ce programme doit être présent dans votre répertoire actuel. Un './' n'a aucun sens lorsque vous exécutez une commande standard située quelque part dans $ PATH. Une commande "quelle commande exécuter" vous indique où se trouve la commande à exécuter dans le $ PATH.

utilisateur7346
la source
0
$ gcc hello.c -o /path/to/someplace/hello

produira un exécutable à un endroit. Si cet emplacement est sur votre chemin, vous pourrez exécuter le fichier. Vous pouvez créer un script si vous souhaitez créer un libellé pour l'action "compilez ce code source à l'aide du gcc et placez un exécutable à un emplacement situé sur votre chemin".

Je vous suggérerais de créer un nouveau répertoire appelé "testbin" ou quelque chose du genre et de le placer sur votre chemin pour garder propres vos répertoires de chemins existants.

Jon Kiparsky
la source
0

./élimine la recherche inutile d'un chemin. ./forcer à rechercher dans le répertoire actuel seulement. Si nous ne donnons pas ./alors il va chercher divers chemin d' accès défini dans le système comme /usr/bin, /usr/sbin/, etc.

utilisateur175959
la source
0

"./" signifie que vous voulez exécuter un fichier dans le répertoire courant, c'est un raccourci pour taper le chemin complet, par exemple:

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

est identique à:

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

Dans l'exemple précédent, vous avez parcouru le répertoire et ses sous-répertoires jusqu'à l'emplacement du fichier et utilisé "./" pour exécuter le fichier dans le répertoire en cours.

celui qui le précède " [racine @ serveur ~] # / chemin / vers / fichier / fichier.pl " exécutera également le fichier si vous êtes paresseux pour "cd" pour vous rendre à l'emplacement du fichier.

Khaled Moustafa
la source
-4

C'est très simple et a de nombreuses utilisations.

  1. Lorsque plusieurs versions de la même application sont installées, elles seront disponibles dans un chemin différent, mais vous pourrez créer un lien vers votre fichier binaire /usr/bin. Par exemple, Python 2.7, Python 2.6 est installé mais / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Si vous êtes sur le chemin /usr/local/binet que vous exécutez Python, celui-ci sera toujours exécuté. La spécification .prendra l'exécutable du dossier actuel.

  1. .- représente toujours exécuter depuis le répertoire en cours. Et ..toujours signifie s'exécute à partir du répertoire précédent.
Ramjee Anna
la source