La #!
ligne est utilisée avant l'exécution du script, puis ignorée lors de son exécution.
Vous demandez quelle est la différence entre une ligne shebang et un commentaire ordinaire.
Une ligne commençant par #!
est tout autant un commentaire qu'une autre ligne commençant par #
. Cela est vrai s'il #!
s'agit de la première ligne du fichier ou ailleurs. #!/bin/sh
a un effet , mais il n'est pas lu par l'interprète lui-même .
#
Ce n'est pas un commentaire dans tous les langages de programmation, mais, comme vous le savez, c'est un commentaire dans les shells de style Bourne, notamment ( sh
et) bash
(ainsi que la plupart des shells de style non Bourne, par exemple csh
). C'est aussi un commentaire en Python . Et c'est un commentaire dans une variété de fichiers de configuration qui ne sont pas vraiment des scripts (comme /etc/fstab
).
Supposons qu'un script shell commence par #!/bin/sh
. C'est un commentaire, et l'interprète (le shell) ignore tout ce qui se trouve sur la ligne après le #
personnage.
Le but d'une #!
ligne n'est pas de donner des informations à l'interprète. Le but de la #!
ligne est d'indiquer au système d'exploitation (ou quel que soit le processus qui lance l'interpréteur) ce qu'il doit utiliser comme interprète .
Si vous appelez le script en tant que fichier exécutable, par exemple en l'exécutant ./script.sh
, le système consulte la première ligne pour savoir si commence par #!
, suivi de zéro ou plus d'espaces, suivi d'une commande. Si tel est le cas, il exécute cette commande avec le nom du script comme argument. Dans cet exemple, il s'exécute /bin/sh script.sh
(ou techniquement /bin/sh ./script.sh
).
Si vous appelez le script en appelant explicitement l'interpréteur, la #!
ligne n'est jamais consultée. Donc, si vous courez sh script.sh
, la première ligne n'a aucun effet. Si script2.sh
la première ligne est #!/usr/games/nibbles
lue, l'exécution sh script2.sh
ne tentera pas d'ouvrir le script nibbles
(mais le ./script2.sh
fera).
Vous remarquerez que dans aucun cas l'extension ( .sh
) du script , si elle en a une, a une incidence sur son exécution. Dans un système de type Unix, cela n’affecte généralement pas la façon dont le script est exécuté. Sur d'autres systèmes, tels que Windows, la #!
ligne shebang peut être entièrement ignorée par le système et l'extension peut déterminer le type d'exécution des scripts. (Cela ne signifie pas que vous devez attribuer des extensions à vos scripts, mais c’est l’une des raisons pour lesquelles elles doivent être correctes.)
#!
a été choisi pour servir cet objectif précisément parce que #
commence un commentaire. La #!
ligne est destinée au système, pas à l'interprète, et l'interprète devrait l'ignorer.
Shebang Line pour les scripts Bash
Vous avez (à l'origine) dit que vous utilisiez #!/bin/sh
des bash
scripts. Vous ne devriez le faire que si le script ne nécessite aucune bash
extension - il sh
doit pouvoir exécuter le script. sh
n'est pas toujours un lien symbolique vers bash
. Souvent, y compris sur tous les systèmes Debian et Ubuntu récents et à distance , sh
un lien symbolique est créé dash
.
Ligne Shebang pour les scripts Python
Vous avez également indiqué (dans la première version de votre question, avant la modification) que vous démarrez vos scripts Python #!/bin/sh read by the interpretor
. Si vous voulez dire cela littéralement, alors vous devriez absolument arrêter de le faire. Si hello.py
commence par cette ligne, l'exécution ./hello.py
s'exécute:
/bin/sh read by the interpretor hello.py
/bin/sh
essaiera d'exécuter un script appelé read
(avec by the interpretor hello.py
comme arguments), read
ne sera (espérons-le) pas trouvé et votre script Python ne sera jamais vu par un interprète Python.
Si vous faites cette erreur mais n'avez pas le problème que je décris, vous invoquez probablement vos scripts Python en spécifiant explicitement l'interpréteur (par exemple, python hello.py
), ce qui a pour effet d'ignorer la première ligne. Lorsque vous distribuez vos scripts à d'autres personnes ou les utilisez longtemps après, il n'est peut-être pas évident que cela leur soit nécessaire. Il est préférable de les réparer maintenant. Ou du moins, supprimez entièrement la première ligne, de sorte que, s’ils ne parviennent pas à s’exécuter avec ./
le message d’erreur, cela aura un sens.
Pour les scripts Python, si vous savez où se trouve (ou sera) l'interpréteur Python, vous pouvez écrire la #!
ligne de la même manière:
#!/usr/bin/python
Ou, s'il s'agit d'un script Python 3, vous devez spécifier python3
, car python
c'est presque toujours Python 2 :
#!/usr/bin/python3
Cependant, le problème est que, même s'il /bin/sh
est censé exister toujours et /bin/bash
presque toujours sur les systèmes bash
livrés avec le système d'exploitation, Python peut exister à divers endroits.
Par conséquent, de nombreux programmeurs Python utilisent ceci à la place:
#!/usr/bin/env python
(Ou #!/usr/bin/env python3
pour Python 3.)
Cela fait que le script se base sur le fait d' env
être au "bon endroit" au lieu de se fier python
au bon endroit. C'est une bonne chose car:
env
est presque toujours situé dans /usr/bin
.
- Sur la plupart des systèmes, celui qui
python
doit exécuter votre script est celui qui apparaît en premier dans le répertoire PATH
. En commençant hello.py
par #!/usr/bin/env python
make ./hello.py
run /usr/bin/env python hello.py
, ce qui est (pratiquement) équivalent à courir python hello.py
.
La raison pour laquelle vous ne pouvez pas utiliser #!python
est que:
- Vous voulez que l'interprète spécifié soit donné par un chemin absolu (c'est-à-dire en commençant par
/
).
- Le processus appelant serait exécuté
python
dans le répertoire en cours . La recherche du chemin lorsque la commande ne contient pas de barre oblique est un comportement spécifique du shell.
Parfois, un script Python ou autre script qui n'est pas un script shell aura une ligne shebang commençant par #!/bin/sh ...
où se ...
trouve un autre code. C'est parfois correct, car il existe des moyens d'appeler le shell ( sh
) compatible Bourne avec des arguments pour le faire appeler un interpréteur Python. (Un des arguments le contiendra probablement python
.) Cependant, dans la plupart des cas, il #!/usr/bin/env python
est plus simple, plus élégant et plus susceptible de fonctionner comme vous le souhaitez.
Lignes Shebang dans d'autres langues
De nombreux langages de programmation et de script, ainsi que d'autres formats de fichiers, utilisent #
comme commentaires. Pour n'importe lequel d'entre eux, un fichier dans la langue peut être exécuté par un programme qui le prend comme argument en spécifiant le programme sur la première ligne suivante #!
.
Dans certains langages de programmation, ce #
n’est normalement pas un commentaire, mais dans un cas particulier, la première ligne est ignorée si elle commence par #!
. Cela facilite l'utilisation de la #!
syntaxe même si, par #
ailleurs, une ligne n'est pas un commentaire.
Lignes Shebang pour les fichiers qui ne s'exécutent pas en tant que scripts
Bien que ce soit moins intuitif, tout fichier dont le format de fichier peut accueillir une première ligne commençant par #!
suivi du chemin complet d'un exécutable peut avoir une ligne shebang. Si vous faites cela, et que le fichier est marqué comme exécutable, vous pouvez l'exécuter comme un programme ... et ainsi l'ouvrir comme un document.
Certaines applications utilisent ce comportement intentionnellement. Par exemple, dans VMware, les .vmx
fichiers définissent des machines virtuelles. Vous pouvez "exécuter" une machine virtuelle comme s'il s'agissait d'un script, car ces fichiers sont marqués comme étant exécutables et comportent une ligne shebang, ce qui les ouvre dans un utilitaire VMware.
Lignes Shebang pour les fichiers qui ne s'exécutent pas comme des scripts mais agissent comme des scripts de toute façon
rm
supprime les fichiers. Ce n'est pas un langage de script. Cependant, un fichier qui commence #!/bin/rm
et qui est marqué comme exécutable peut être exécuté. Lorsque vous l'exécutez, il rm
est appelé, ce qui le supprime.
Ceci est souvent conceptualisé comme "le fichier se supprime lui-même". Mais le fichier ne fonctionne pas vraiment du tout. Cela ressemble plus à la situation décrite ci-dessus pour les .vmx
fichiers.
Néanmoins, comme la #!
ligne facilite l'exécution d'une commande simple (y compris les arguments de ligne de commande), vous pouvez effectuer certains scripts de cette manière. Comme exemple simple d'un "script" plus sophistiqué que #!/bin/rm
, considérons:
#!/usr/bin/env tee -a
Cela prend les entrées de l'utilisateur de manière interactive, les renvoie ligne par ligne à l'utilisateur et les ajoute à la fin du fichier "script".
Utile? Pas très. Conceptuellement intéressant? Totalement! Oui. (Quelque peu.)
Concepts de programmation / script similaires (juste pour le plaisir)
#include
. Là aussi, le#
n'est pas censé être un commentaire.