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


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


86
2017-07-16 11:58


origine


un peu plus d'informations: le point est un raccourci pour 'source', qui est une commande intégrée du shell bash. plus d'informations sur la commande peuvent être obtenues en passant en revue le "man bash". - Nathan
@nathan non ce n'est pas le . dans cet exemple est le répertoire de travail actuel. le source sténographie est . file.sh c'est-à-dire avec un espace, pas un /. Vous ne pouvez pas générer un programme compilé: ELF! = Bash ... - tobyodavies
@tobyodavies merci de clarifier - en effet, j'étais confus au sujet des différences entre ./ et . - Nathan
Cela doit être un doublon. C'est la toute première chose que tout le monde rencontre lors de la création de son propre programme sur UniX / Linux. - Peter Mortensen
Autres candiates pour duplicata: Mon programme ne peut pas s'exécuter avec l'erreur «commande introuvable» et Quelle est la signification de ./ avant un chemin donné?. - Peter Mortensen


Réponses:


Lorsque vous tapez le nom d'un programme tel que a.out le système recherche 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 $PATH dans un terminal.

Le système examine ces répertoires dans l'ordre indiqué et s'il ne trouve pas le programme command not found Erreur.

Pré-commande de la commande avec ./ dit effectivement "oubliez le PATH, je veux que vous ne regardiez que dans le répertoire actuel".

De même, vous pouvez indiquer au système de rechercher uniquement un autre emplacement spécifique en ajoutant au préalable un chemin relatif ou absolu tel que:

../ signifie dans le répertoire parent par exemple ../hello Cherchez bonjour dans le répertoire parent.

./Debug/hello : "chercher hello dans le sous-répertoire Debug de mon répertoire actuel. "

ou /bin/ls : "chercher ls dans l'annuaire /bin"

Par défaut, le répertoire en cours n'est pas dans le chemin, car il est considéré comme un risque de sécurité. Voir Pourquoi est-ce . pas dans le chemin par défaut? sur Superuser 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.


113
2017-07-16 13:20



Ce. +1 Ne pas ajouter . à ton PATH (comme le suggèrent actuellement les 2 autres réponses) en raison du risque de sécurité mentionné dans cette réponse. - Day
Il peut également être intéressant de noter qu'il n'y a rien de spécial à propos de .ici, vous pouvez utiliser un chemin complet ou relatif vers un exécutable, par ex. /home/user/foo/a.out ou ./build/a.out - tobyodavies
@obyodavies; Réellement . est spécial parce que cela signifie "mon répertoire actuel" et que n'importe quel répertoire peut être trouvé par l'utilisateur avec des privilèges de lecture et d'exécution. Ceci est potentiellement plus dangereux que d'ajouter un chemin spécifique complet. - Warren Hill
@WarrenHill lorsque vous envisagez de l'ajouter à votre chemin, oui, c'est assez différent. Cependant, en termes de syntaxe bash, . n'a pas de statut particulier, c'est juste un chemin qui pourrait tout aussi bien commencer par / et ./blah travaillerait aussi bien avec cat ou grep comme une invite bash. - tobyodavies
@tobyodavies: OK J'ai édité ma réponse pour inclure votre point. - Warren Hill


La raison en est simple.

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

En exigeant ./ pour être utilisé en avant, le shell sait que vous voulez exécuter l'application avec le nom donné et non une commande intégrée portant ce nom.


24
2017-12-16 03:21



Merci George. Merci (et je pense que j'ai entendu dire il y a quelques années - il faut rester assez longtemps avec Linux pour que ces choses se produisent) - Doug
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, plus vous lisez, plus ma réponse est fausse. - Ahmed Masud


./ exécute des fichiers qui ne sont pas dans votre $PATH, il exécute plutôt le fichier dans le répertoire en cours (ou via 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) vers eux.

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

  • Lorsque vous exécutez une commande ou qu'un programme tente de créer une exec syscall (une méthode spéciale du noyau, comment les programmes sont démarrés), 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 répertoires, 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à sur la ligne de commande, vous pouvez simplement taper chmod +x finename.

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

    alt text

Vous pouvez maintenant copier le fichier dans l'un des répertoires de PATH, pour voir ceux qui s'y trouvent - 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, cat, et le déplacer vers /usr/local/sbin, il est exécuté au lieu du bon cat, qui réside dans /bin. Vous pouvez savoir où sont vos fichiers en utilisant type cat et whereis cat.


16
2017-12-16 03:18



Une chose à noter: sa question semble indiquer qu’il a compilé et lié quelque chose avec gcc, qui définit automatiquement le bit d'exécution. - Nathan Osman


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, disons gedit, le terminal ira chercher dans certains répertoires (prédéfinis) contenant des applications (les binaires des applications). Les noms de ces répertoires sont contenus dans une variable appelée PATH. Vous pouvez voir ce que contient cette variable en exécutant echo $PATH. Voir ces répertoires séparés par :? Ce sont les répertoires dans lesquels le terminal va chercher, si vous tapez simplement gedit, nautilus, ou a.out. Comme vous pouvez le voir, le chemin de votre a.out programme n'est pas là. Quand tu fais ./a.out, vous dites au terminal "regardez dans le répertoire actuel, et exécutez a.out, et ne va pas regarder PATH.

Solution 1

Si vous ne voulez pas taper ./ à chaque fois, vous devrez ajouter a.outle répertoire dans $PATH. Dans les instructions suivantes, je suppose que le chemin vers a.out est /path/to/programs/, mais vous devriez 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
    

    La source: Variables d'environnement persistantes

  2. Déconnectez-vous et reconnectez-vous. Vous pourrez maintenant exécuter a.out sans pour autant ./ à partir de n'importe quel 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 conseille d’avoir un répertoire appelé "myPrograms" par exemple, et d’y placer tous vos programmes.

Solution 2

Remarque: changement userName à votre nom d'utilisateur Ubuntu actuel.

Et si vous avez d'autres programmes à exécuter? Et ils sont tous dans des dossiers différents? Eh bien, une solution "plus organisée" serait de créer un dossier appelé bin sous votre répertoire Home, et ajoutez des liens symboliques (raccourcis) dans ce dossier. Voici comment:

  1. mkdir /home/userName/bin

    • Cela va créer le dossier bin sous votre répertoire personnel.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Cela créera un "lien symbolique" (essentiellement un raccourci) de votre a.out programme sous bin.
  3. Déconnectez-vous et reconnectez-vous. Vous pourrez maintenant exécuter a.out sans pour autant ./ à partir de n'importe quel répertoire.

Maintenant, chaque fois que vous avez un autre programme ailleurs, disons le programme b.in sur votre bureau, il vous suffit de: ln -s /home/userName/Desktop/b.in /home/userName/bin, et vous pourrez alors l'exécuter sans ./ ainsi que.

Remarque: grâce à @ Commentaire de Joe, lorsque vous effectuez des sauvegardes, les liens symboliques doivent être gérés spécialement. Par défaut, rsync ne les traite pas du tout, alors quand vous restaurez, ils ne sont pas là.


11
2017-07-16 13:27



C'est un truc pratique s'il est utilisé avec parcimonie. En l'utilisant beaucoup, votre système fait des choses auxquelles quelqu'un d'autre ne s'attendrait pas. De plus, lorsque vous effectuez des sauvegardes, les liens symboliques doivent être gérés spécialement. Par défaut, rsync ne les traite pas du tout, alors quand vous restaurez, ils ne sont pas là. - Joe


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

Je me souviens avoir posé cette question à mon supérieur il y a longtemps, il a dit que je devrais ajouter . à mon chemin pour que quand je le fais a.out il cherche 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 alien ou quelque chose, et un fichier exécutable malveillant appelé ls existe là-bas, puis avoir . sur votre chemin est une très mauvaise idée. Non pas que vous rencontrerez ce problème très souvent, simplement en disant.


1
2017-12-16 03:32



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


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


0
2017-12-16 11:06





$ gcc hello.c -o /path/to/someplace/hello

produira un exécutable à un certain 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 une étiquette pour l'action "compiler ce code source à l'aide de gcc et placer un exécutable à un emplacement situé sur votre chemin"

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


0
2017-07-16 18:35





./ élimine la recherche inutile d'un chemin. ./ forcer à rechercher dans le répertoire en cours uniquement. Si on ne donne pas ./ alors il recherchera divers chemin mis dans le système comme /usr/bin, /usr/sbin/, etc.


0
2017-07-17 11:11





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

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

est la même que:

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

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

celui qui l'a précédé "[root @ server ~] # / chemin / vers / fichier / fichier.plmsgstr "exécutera également le fichier si vous êtes paresseux pour" cd "votre chemin vers l’emplacement du fichier.


0
2018-04-25 00:20