Lors de l'exécution de scripts en bash, je dois écrire ./
au début:
$ ./manage.py syncdb
Si je ne le fais pas, j'obtiens un message d'erreur:
$ manage.py syncdb
-bash: manage.py: command not found
Quelle est la raison pour ça? Je pensais que c'était .
un alias pour le dossier actuel, et donc ces deux appels devraient être équivalents.
Je ne comprends pas non plus pourquoi je n'ai pas besoin ./
lors de l'exécution d'applications, telles que:
user:/home/user$ cd /usr/bin
user:/usr/bin$ git
(qui fonctionne sans ./
)
bash
shell
unix
command-line
Dan Abramov
la source
la source
Réponses:
Parce que sous Unix, généralement, le répertoire actuel n'est pas dans
$PATH
.Lorsque vous tapez une commande, le shell recherche une liste de répertoires, comme spécifié par la
PATH
variable. Le répertoire actuel ne figure pas dans cette liste.La raison de ne pas avoir le répertoire actuel sur cette liste est la sécurité.
Disons que vous êtes root et allez dans le répertoire d'un autre utilisateur et tapez
sl
au lieu dels
. Si le répertoire courant se trouvePATH
, le shell essaiera d'exécuter lesl
programme dans ce répertoire (puisqu'il n'y a pas d'autresl
programme). Cesl
programme pourrait être malveillant.Il fonctionne avec
./
car POSIX spécifie qu'un nom de commande qui contient 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 il./
est plus court et plus facile à écrire.ÉDITER
Cette
sl
partie n'était qu'un exemple. Les répertoiresPATH
sont recherchés séquentiellement et lorsqu'une correspondance est établie, le programme est exécuté. Ainsi, selon l'PATH
apparence, taper une commande normale peut ou peut ne pas être suffisant pour exécuter le programme dans le répertoire en cours.la source
ls
exécutable..\my.bat
etc pour exécutersl
commande appelée locomotive à vapeur bien qu'elle ne soit pas disponible par défaut ;-)Lorsque bash interprète la ligne de commande, il recherche les commandes aux emplacements décrits dans la variable d'environnement
$PATH
. Pour le voir, tapez:Vous aurez quelques chemins séparés par des deux-points. Comme vous le verrez, le chemin actuel
.
n'est généralement pas dans$PATH
. Bash ne peut donc pas trouver votre commande si elle se trouve dans le répertoire courant. Vous pouvez le changer en ayant:Cette ligne ajoute le répertoire courant
$PATH
afin que vous puissiez faire:Il n'est pas recommandé car il a un problème de sécurité, et vous pouvez avoir des comportements étranges, car cela
.
varie selon le répertoire dans lequel vous vous trouvez :)Éviter:
Comme vous pouvez «masquer» une commande standard et ouvrir la porte à une brèche de sécurité :)
Juste mes deux cents.
la source
Votre script, dans votre répertoire personnel, ne sera pas trouvé lorsque le shell
$PATH
variable d'environnement pour trouver votre script.Le
./
dit 'regardez dans le répertoire courant pour mon script plutôt que de regarder tous les répertoires spécifiés dans$PATH
'.la source
Lorsque vous incluez le '.' vous donnez essentiellement le "chemin complet" au script bash exécutable, donc votre shell n'a pas besoin de vérifier votre variable PATH. Sans le '.' votre shell va regarder dans votre variable PATH (que vous pouvez voir en exécutant
echo $PATH
pour voir si la commande que vous avez tapée se trouve dans l'un des dossiers de votre PATH. Si ce n'est pas le cas (comme c'est le cas avec manage.py), il le dit Impossible de trouver le fichier. Il est considéré comme une mauvaise pratique d'inclure le répertoire actuel dans votre PATH, ce qui est expliqué assez bien ici: http://www.faqs.org/faqs/unix-faq/faq/part2/section- 13.htmlla source
Sur * nix, contrairement à Windows, le répertoire courant n'est généralement pas dans votre
$PATH
variable. Ainsi, le répertoire actuel n'est pas recherché lors de l'exécution des commandes. Vous n'avez pas besoin./
d'exécuter des applications car ces applications sont dans votre $ PATH; ils sont très probablement dans/bin
ou/usr/bin
.la source
Cette question a déjà des réponses impressionnantes, mais je voulais ajouter que, si votre exécutable est sur le PATH, et que vous obtenez des sorties très différentes lorsque vous exécutez
à ceux que vous obtenez si vous courez
(disons que vous rencontrez des messages d'erreur avec l'un et non avec l'autre), le problème pourrait être que vous avez deux versions différentes de l'exécutable sur votre machine: une sur le chemin et l'autre non.
Vérifiez cela en exécutant
quel exécutable
et
Il a résolu mes problèmes ... J'avais trois versions de l'exécutable, dont une seule a été compilée correctement pour l'environnement.
la source
Justification de la
/
règle POSIX PATHLa règle a été mentionnée à: Pourquoi avez-vous besoin de ./ (barre oblique) avant le nom de l'exécutable ou du script pour l'exécuter dans bash?mais je voudrais expliquer pourquoi je pense que c'est une bonne conception plus en détail.
Premièrement, une version complète explicite de la règle est:
/
(par exemple./someprog
,/bin/someprog
,./bin/someprog
): CWD est utilisé et est non PATH/
(par exemplesomeprog
): PATH est utilisé et CWD ne l'est pasSupposons maintenant que l'exécution:
rechercherait:
Ensuite, si vous vouliez courir à
/bin/someprog
partir de votre distribution, et vous avez fait:cela fonctionnerait parfois, mais d'autres échoueraient, car vous pourriez être dans un répertoire qui contient un autre sans rapport
someprog
programme .Par conséquent, vous apprendrez bientôt que ce n'est pas fiable et vous finirez toujours par utiliser des chemins absolus lorsque vous souhaitez utiliser PATH, ce qui ira à l'encontre de l'objectif de PATH.
C'est aussi pourquoi avoir des chemins relatifs dans votre PATH est une très mauvaise idée. Je te regarde,
node_modules/bin
.À l'inverse, supposons que l'exécution:
Rechercherait:
Ensuite, si vous venez de télécharger un script à
someprog
partir d'un référentiel git et que vous vouliez l'exécuter à partir de CWD, vous ne seriez jamais sûr que c'est le programme réel qui s'exécuterait, car peut-être que votre distribution a un:qui est dans votre CHEMIN à partir d'un paquet que vous avez installé après avoir trop bu après Noël l'année dernière.
Par conséquent, encore une fois, vous seriez obligé de toujours exécuter des scripts locaux relatifs à CWD avec des chemins d'accès complets pour savoir ce que vous exécutez:
ce qui serait également extrêmement ennuyeux.
Une autre règle que vous pourriez être tenté de proposer serait:
mais encore une fois, cela oblige les utilisateurs à toujours utiliser des chemins absolus pour les scripts non-PATH avec
"$(pwd)/someprog"
.La
/
règle de recherche de chemin offre une solution simple à retenir au problème de:PATH
PATH
ce qui rend super facile de toujours savoir ce que vous exécutez, en s'appuyant sur le fait que les fichiers dans le répertoire en cours peuvent être exprimés soit comme
./somefile
ousomefile
, et donc il donne une signification particulière à l'un d'eux.Parfois, c'est légèrement ennuyeux que vous ne puissiez pas rechercher par
some/prog
rapport àPATH
, mais je ne vois pas de solution plus saine à cela.la source
Lorsque le script n'est pas dans le chemin, il est nécessaire de le faire. Pour plus d'informations, consultez http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html
la source
Tous ont une excellente réponse à la question, et oui, cela ne s'applique que lors de son exécution sur le répertoire en cours, sauf si vous incluez le chemin absolu. Voir mes exemples ci-dessous.
En outre, le (point-slash) était logique pour moi lorsque j'ai la commande sur le dossier enfant tmp2 (/ tmp / tmp2) et qu'il utilise (double point-slash).
ÉCHANTILLON:
la source