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 simplement a.out
? Y a-t-il une solution pour cela?
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 génère une erreur command not found
.
Le préfixe précédant la commande avec ./
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 avec un chemin relatif ou absolu, tel que:
../
signifie dans le répertoire parent, par exemple ../hello
, recherchez hello dans le répertoire parent.
./Debug/hello
: "recherchez hello
dans le sous-répertoire Debug de mon répertoire actuel."
ou /bin/ls
: "recherchez ls
dans 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-ce que .n'est pas dans le chemin par défaut? sur le 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.
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 à la place de la commande intégrée. Ce serait un problème de sécurité si rien d’autre.
En exigeant que ./
soit utilisé devant, Shell sait que vous souhaitez exécuter l'application avec le nom indiqué et non avec une commande intégrée portant ce nom.
./
exécute les fichiers qui ne sont pas dans votre $PATH
, 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. si vous avez un fichier appelé ls
dans votre répertoire personnel, le fait qu'il ne soit pas dans votre PATH empêchera bash de le confondre avec le vrai ls
. La variable PATH définit également l'ordre de recherche:
exec
(une méthode spéciale du noyau, le mode de démarrage des programmes), le système recherche le fichier en parcourant chacun des répertoires de votre chemin 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:
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 - tapez 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éplacez vers /usr/local/sbin
, il est exécuté à la place du cat
approprié, qui réside dans /bin
. Vous pouvez trouver où sont vos fichiers en utilisant type cat
et whereis cat
.
./
avant d'exécuter un programme?Dans le terminal, chaque fois que vous tapez le nom d'une application, par exemple gedit
name__, 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
name__. 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 dans lesquels le terminal va chercher, si vous tapez simplement gedit
name__, nautilus
ou a.out
. Comme vous pouvez le constater, le chemin de votre programme a.out
n’y figure pas. Quand vous faites ./a.out
, vous dites au terminal "regardez dans le répertoire actuel, exécutez a.out
et ne regardez pas dans PATH
name__.
Si vous ne voulez pas taper ./
à chaque fois, vous devez ajouter le répertoire de a.out
dans $PATH
. Dans les instructions suivantes, je suppose que le chemin d'accès à a.out
est /path/to/programs/
, mais vous devez le remplacer par votre chemin d'accès réel.
Ajoutez simplement la ligne suivante à la fin du fichier ~/.pam_environment
:
PATH DEFAULT=${PATH}:/path/to/programs
Déconnectez-vous et reconnectez-vous. Vous pourrez désormais exécuter a.out
sans ./
à 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 conseillerais par exemple d'avoir un répertoire appelé "mes programmes" et de placer tous vos programmes sous celui-ci.
Remarque: remplacez
userName
par votre 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é bin
dans votre répertoire de base et à ajouter des liens symboliques (raccourcis) dans ce dossier. Voici comment:
mkdir /home/userName/bin
bin
dans votre répertoire de base.ln -s /path/to/programs/a.out /home/userName/bin
a.out
sous bin
name__.Déconnectez-vous et reconnectez-vous. Vous pourrez désormais exécuter a.out
sans ./
à 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, tout ce que vous avez à faire est: ln -s /home/userName/Desktop/b.in /home/userName/bin
et vous pourrez ensuite l'exécuter sans également ./
.
Remarque: grâce à commentaire de @ Joe , lorsque vous effectuez des sauvegardes, les liens symboliques doivent être traités de manière spécifique. Par défaut,
rsync
ne les traite pas du tout. Par conséquent, lors de la restauration, ils ne sont pas présents.
Comme George l'a souligné dans sa réponse, cela vous aide à noter que votre en cours d'exécution un fichier du répertoire de travail en cours (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 pour que, lorsque je le ferais, a.out
apparaisse 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 vous trouvez sur un répertoire réseau étranger ou quelque chose d’autre et qu’un fichier exécutable malveillant appelé ls
existe déjà, il est très mauvais d’avoir .
dans votre chemin. Non pas que vous rencontriez ce problème très souvent, simplement en disant.
./
élimine la recherche inutile d'un chemin. ./
force à rechercher uniquement dans le répertoire en cours. Si nous ne donnons pas ./
, il recherchera différents chemins définis dans le système, tels que /usr/bin
, /usr/sbin/
, etc.
Un './' a du sens lorsque vous exécutez un programme qui est 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 située quelque part dans $ PATH. Une commande "quelle commande exécuter" vous indique où se trouve la commande à exécuter dans le $ PATH.
"./" 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 avez 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 vous attardez à "cd" pour vous rendre à l'emplacement du fichier.
$ 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 de 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.