./ (barre oblique) est-il une commande?

16

Au cœur de la question:

La question s'est posée alors que je ne pouvais pas installer le logiciel, donc je pose vraiment des questions sur ./ parce que je ne le savais pas et que la sortie "commande non trouvée" me confondait sur ce qu'était réellement la commande.

Le contexte:

Je souhaite installer le fichier truecrypt-7.2-setup-x86.

Les instructions disent d'utiliser la commande:

sudo ./truecrypt-7.2-setup-x86

Mais la sortie est:

sudo: ./truecrypt-7.2-setup-x86: command not found

MISE À JOUR: pour être complet, dans le test, j'étais dans le dossier de fichiers mais je n'avais pas encore rendu le fichier exécutable (chmod + x).

Ubuntubu
la source
1
La ./partie de la commande dit "Regardez dans le répertoire courant et exécutez la commande" truecrypt-7.2-setup-x86 "d'ici". Vous devez exécuter cette commande à partir du répertoire dans lequel vous avez décompressé le fichier.
Charles Green
2
@Videonauth - Pas vraiment, personnellement, je ne pense pas que cela élève le niveau d'une réponse.
Charles Green
1
@Zanna J'ai testé un script sans autorisations d'exécution, et l'erreur renvoyée était une erreur d'autorisation manquante, pas une commande introuvable.
Charles Green
2
@ubuntubu OK, très bien, vous avez déménagé dans le répertoire - bien. Petit commentaire sur l'édition, cependant. La commande devrait être chmod +x, chmod -xc'est le contraire - elle supprime les autorisations exécutables
Sergiy Kolodyazhnyy
4
Le titre de la question est très différent du corps; peut-être que cela devrait être corrigé?
David Z

Réponses:

24

./n'est pas une commande. La commande est ./truecrypt-7.2-setup-x86.

Votre shell et vos programmes comme sudotraiteront une commande comme un chemin d'accès lorsqu'elle contient au moins un /caractère. Étant donné que .représente le répertoire dans lequel vous vous trouvez actuellement, ./truecrypt-7.2-setup-x86nomme le fichier truecrypt-7.2-setup-x86dans le répertoire actuel. S'il n'existe pas de fichier de ce type, ou s'il existe mais que le fichier ne peut pas être exécuté, vous obtiendrez un message d'erreur.

Lorsqu'une commande ne contient pas de barre oblique, les répertoires répertoriés dans $PATHsont recherchés, comme le dit Sergiy Kolodyazhnyy . Le répertoire courant est pas automatiquement recherché - et il est pas recommandé de mettre .en $PATH. De cette façon, vous n'exécutez pas accidentellement des choses que vous ne pensiez pas exécuter parce que vous aviez justement cdd dans un répertoire qui les contient.

Écrire ./avant le nom d'un exécutable dans le répertoire courant la manière courante de l'exécuter, mais ce n'est en fait pas une syntaxe spéciale. Par exemple, si vous avez gâché votre $PATHet que vous deviez exécuter une commande comme ls, vous pourriez écrire /bin/ls. Non .est nécessaire dans ce cas ou en général; ce qu'il faut, c'est /quelque part dans le chemin pour signifier que vous voulez dire que c'est un chemin.

Puisqu'il .s'agit toujours du répertoire courant et qu'il ne /s'agit que du séparateur de répertoires, la première chose à faire est de vérifier que le fichier que vous avez nommé existe réellement dans le répertoire courant. (Si c'est le cas, vérifiez ses autorisations , comme l' explique Charles Green . Mais si vous avez extrait le fichier d'une archive, il aura généralement déjà des autorisations exécutables s'il est destiné à être exécuté.)

Eliah Kagan
la source
21

La partie ./ de la commande dit "Regardez dans le répertoire courant et exécutez la commande 'truecrypt-7.2-setup-x86' à partir d'ici". Vous devez exécuter cette commande à partir du répertoire dans lequel vous avez décompressé le fichier.

Cela peut être testé: dans la même fenêtre de terminal où vous essayez la commande, entrez la commande ls -l true*- si le fichier est présent dans le répertoire de travail actuel, une liste montrant le fichier (et un tas d'informations supplémentaires) sera affichée.

Comme Zanna l'a noté dans les commentaires, votre fichier peut ne pas avoir d'autorisations d'exécution - cela peut être corrigé facilement. Comme test, mon répertoire montre

chick@dad:~/test$ ls -l
total 4
-rw-r--r-- 1 chick chick 788 Oct 27 06:15 rFullBack
chick@dad:~/test$

et le fichier "rFullBack" répertorie '-rw-' comme ma permission, pour lire et écrire le fichier. Je peux exécuter la commande chmod +x rFullBacket la liste des répertoires devient

chick@dad:~/test$ ls -l
total 4
-rwxr-xr-x 1 chick chick 788 Oct 27 06:15 rFullBack
chick@dad:~/test$

Là, mes autorisations sont maintenant «-rwx», indiquant que je peux exécuter le fichier.


En bref, si le fichier existe dans votre répertoire

exécutez la commande

chmod +x ./truecrypt-7.2-setup-x86

puis la commande

sudo ./truecrypt-7.2-setup-x86
Charles Green
la source
1
Pas assez. Il répertorie en rw-tant que votre autorisation - -avant qu'il ne soit pour définir [gu] id et les bits collants.
Duncan X Simpson
@DuncanXSimpson Merci - J'ai mis à jour un peu la description des autorisations, mais je vais ignorer les bits setguid et sticky pour cette réponse!
Charles Green
8

Comment fonctionne l'appel de commandes dans le shell

Non, ce n'est pas une commande. Le fonctionnement des shells est lorsque vous tapez une ligne de texte, le premier mot sera traité comme une commande, et si la commande ne fait pas partie de celles intégrées au shell, le shell regardera tous les emplacements répertoriés dans PATH la variable d'environnement .

Que se passe-t-il si lorsque la commande que vous souhaitez exécuter se trouve dans le même répertoire que celui que vous avez actuellement localisé mais que ce répertoire ne figure pas dans la liste des PATHrépertoires? C'est à ce moment que vous devez utiliser ./. C'est en quelque sorte exactement la même chose que de faire/bin/bash - vous dites au shell où se trouve votre commande souhaitée, un chemin complet vers elle. Et en cas de ./ vous dites de shell "regardez dans ce répertoire". La partie si importante est que vous devez être dans le même répertoire où se trouve le fichier.

Bien sûr, pour exécuter réellement un exécutable, il doit avoir un bit exécutable défini, vous en aurez donc besoin chmod +x ./my_file.

Donc, les étapes importantes:

  1. cd où vous avez enregistré le fichier; si c'est le cas ~/Downloads,cd ~/Downloads
  2. Exécuter chmod +x ./truecrypt-7.2-setup-x86, cela dit "rendre le fichier truecrypt-7.2-setup-x86 qui est dans ce répertoire exécutable"
  3. Et maintenant sudo ./truecrypt-7.2-setup-x86

Notez que l'utilisation de ./n'est pas un comportement aléatoire, mais est en fait une norme, spécifiée par la norme Portable Operating System Interface (aka POSIX) , voir spécifiquement la section "Recherche et exécution de commandes".

Reproduire l'erreur

$ # my script is in ~/Downloads folder
$ stat -c "%n" /home/xieerqi/Downloads/my_script.sh                         
/home/xieerqi/Downloads/my_script.sh
$ # if I run sudo ./my_script.sh, we get an error
$ sudo ./my_script.sh
[sudo] password for xieerqi: 
sudo: ./my_script.sh: command not found
$ # of course the command not found because file is not in ./, not in this dir
$ # this is not  sudo's problem
$ # but sudo does indeed show the same error even if you're in same directory
$ cd ./Downloads/                                                                                                                                                      
$ sudo ./my_script.sh                                                                                                                                                  
[sudo] password for xieerqi: 
sudo: ./my_script.sh: command not found

REMARQUE : le message d'erreur donné par sudoest manifestement trompeur, c'est donc quelque chose à garder à l'esprit; Cependant, veuillez noter que ce n'était pas le cœur de la question que OP pose.

Documentation et références

Dans le bashmanuel 4.3, section "EXÉCUTION DE COMMANDE":

Si le nom n'est ni une fonction shell ni une fonction intégrée, et ne contient pas de barres obliques, bash recherche dans chaque élément du PATH un répertoire contenant un fichier exécutable de ce nom.

De Pourquoi avez-vous besoin de ./ (barre oblique) avant le nom du script pour l'exécuter dans bash? :

Il fonctionne avec ./ car POSIX spécifie qu'un nom de commande contenant un / sera utilisé directement comme nom de fichier, supprimant une recherche dans $ PATH. Vous auriez pu utiliser le chemin complet pour obtenir exactement le même effet, mais ./ est plus court et plus facile à écrire.

Sergiy Kolodyazhnyy
la source
En fait, la sudosortie est trompeuse. Si vous essayez même sans sudo, vous obtiendrez une autre erreur de bash: Permission denied. Et à juste titre, puisque vous n'avez pas donné au script la permission de s'exécuter (via chmod +x).
Ruslan
@Ruslan le fait que la sudosortie est trompeuse est vrai, mais c'est l'erreur qui apparaît. Cela pourrait être quelque chose à signaler aux développeurs et à les laisser y remédier. Cependant, ce n'est pas le cœur de la discussion - nous devions déterminer ce que l'OP a fait pour produire une telle erreur et les guider vers la bonne voie. Que ce soit trompeur ou non - ce n'est pas le problème ici.
Sergiy Kolodyazhnyy
D'une autre manière, ce n'est pas exactement la même chose que l'utilisation /bin/bash: cela ne vous permet pas d'exécuter un script sur lequel vous n'avez pas l'autorisation d'exécution. Lorsque vous faites précéder le nom du script par /bin/bash, le fait qu'il /bin/bashsoit exécutable est tout ce qui compte, car c'est la commande en cours d'exécution. Lorsque vous ne le faites pas, le script lui-même est en cours d'exécution, ce qui entraîne à son tour l' #!invocation de votre shell actuel ou de tout ce qui se trouve sur la ligne supérieure
Monty Harder
@MontyHarder /bin/bashn'est qu'un exemple ici. Le fait que nous appelions /bin/bashet ./script.sh en spécifiant le chemin vers la chose en cours d'exécution - c'est la même chose. Le préfacement du script avec bash script.shou /bin/bash script.shest une rubrique entièrement différente, où vous exécutez un exécutable et lui passez un argument en tant qu'argument - qui, soit dit en passant, peut casser si la syntaxe est écrite pour autre chose que le shell que vous appelez, par exemple csh. /bin/bashest bien exécutable, mais le fait est que vous spécifiez toujours le chemin d'accès complet.
Sergiy Kolodyazhnyy
2
@SergiyKolodyazhnyy Préfacer un nom de script avec /bin/bashou même simplement bashest également un moyen courant de résoudre le manque d'autorisations exécutables sur le script. La spécification du chemin d'accès complet au script ne résout pas ce problème. C'est donc /bin/bashun exemple particulièrement mauvais dans ce cas spécifique.
Monty Harder