Réponse courte
Dans votre question, la deuxième commande n'utilise ni le .
shell intégré, ni le source
script intégré. Au lieu de cela, vous exécutez le script dans un shell séparé, en l'appelant par son nom, comme vous le feriez avec tout autre fichier exécutable. Cela lui donne un ensemble de variables séparé (cependant, si vous exportez une variable dans son shell parent, ce sera une variable d'environnement pour tout processus enfant et sera donc incluse dans les variables d'un shell enfant ). Si vous modifiez le /
en un espace, cela le ferait avec le .
paramètre prédéfini, ce qui équivaut à source
.
Explication étendue
Il s'agit de la syntaxe du source
shell intégré, qui exécute le contenu d'un script dans le shell actuel (et donc avec les variables du shell actuel):
source testenv.sh
C'est la syntaxe de la commande .
intégrée, qui fait la même chose que source
:
. testenv.sh
Cependant, cette syntaxe exécute le script en tant que fichier exécutable, en lançant un nouveau shell pour l'exécuter:
./testenv.sh
Ce n'est pas en utilisant le .
intégré. Cela .
fait plutôt partie du chemin du fichier que vous exécutez. En règle générale, vous pouvez exécuter n’importe quel fichier exécutable dans un shell en l’appelant avec un nom contenant au moins un /
caractère. Pour exécuter un fichier dans le répertoire actuel, ./
le plus facilement est de le précéder . À moins que le répertoire en cours ne se trouve dans votre PATH
, vous ne pouvez pas exécuter le script avec la commande testenv.sh
. Cela empêche les personnes d'exécuter accidentellement des fichiers du répertoire en cours lorsqu'elles ont l'intention d'exécuter une commande système ou un autre fichier existant dans un répertoire répertorié dans la PATH
variable d'environnement.
Étant donné que l’exécution d’un fichier par son nom (plutôt que avec source
ou .
) l’exécute dans un nouveau shell, celui-ci aura son propre ensemble de variables. Le nouveau shell hérite des variables d'environnement du processus appelant (qui est dans ce cas votre shell interactif) et ces variables d'environnement deviennent des variables shell dans le nouveau shell. Cependant, pour qu'une variable shell soit transmise au nouveau shell, l'un des éléments suivants doit être le cas:
La variable shell a été exportée, ce qui en fait une variable d’environnement. Utilisez le export
shell intégré pour cela. Dans votre exemple, vous pouvez utiliser export MY_VAR=12345
pour définir et exporter la variable en une étape, ou si elle est déjà définie, vous pouvez simplement l'utiliser export MY_VAR
.
La variable shell est explicitement définie et transmise pour la commande que vous exécutez, ce qui en fait une variable d'environnement pour la durée de la commande en cours d'exécution. Cela accomplit généralement que:
MY_VAR=12345 ./testenv.sh
Si MY_VAR
est une variable shell qui n'a pas été exportée, vous pouvez même exécuter testenv.sh
avec MY_VAR
passé en tant que variable d'environnement en la définissant elle-même :
MY_VAR="$MY_VAR" ./testenv.sh
./
La syntaxe pour les scripts nécessite une ligne de hachage pour fonctionner (correctement)
Soit dit en passant, s'il vous plaît noter que, lorsque vous invoquez un exécutable par son nom comme ci - dessus (et non pas avec la .
ou du source
shell-ins), ce programme shell est utilisé pour exécuter est pas généralement déterminé par ce shell que vous lancez depuis . Au lieu:
Pour les fichiers binaires, le noyau peut être configuré pour exécuter des fichiers de ce type particulier. Il examine les deux premiers octets du fichier pour un "nombre magique" indiquant quel type d'exécutable binaire il s'agit. Voici comment les fichiers binaires exécutables peuvent être exécutés.
Ceci est, bien sûr, extrêmement important, car un script ne peut pas s'exécuter sans un interpréteur ou un interpréteur, qui est un binaire exécutable! De plus, de nombreuses commandes et applications sont des fichiers binaires compilés plutôt que des scripts.
( #!
est la représentation textuelle du "nombre magique" indiquant un texte exécutable.)
Pour les fichiers supposés être exécutés dans un shell ou dans un autre langage interprété, la première ligne est la suivante:
#!/bin/sh
/bin/sh
peut être remplacé par tout autre shell ou interpréteur destiné à exécuter le programme. Par exemple, un programme Python peut commencer par la ligne suivante:
#!/usr/bin/python
Ces lignes s'appellent hashbang, shebang et un certain nombre d'autres noms similaires. Voir cette entrée FOLDOC , cet article de Wikipedia et l'interprète lit-il #! / Bin / sh? pour plus d'informations.
Si un fichier texte est marqué comme exécutable et que vous l'exécutez à partir de votre shell (comme ./filename
) mais qu'il ne commence pas par #!
, le noyau ne parvient pas à l'exécuter. Cependant, voyant que cela est arrivé, votre shell essayera de l'exécuter en transmettant son nom à un shell. Il y a peu d' exigences imposées à ce shell qui est ( « la coquille doit exécuter une commande équivalent à avoir un shell invoqué ... » ). En pratique , certains obus - y compris bash
* - exécutent une autre instance d’eux-mêmes, tandis que d’autres utilisent/bin/sh
. Je vous recommande vivement d'éviter cela et d'utiliser plutôt une ligne hashbang (ou exécutez le script en le transmettant à l'interpréteur souhaité, par exemple bash filename
).
* Manuel GNU Bash , 3.7.2 Recherche et exécution de commandes : "Si cette exécution échoue parce que le fichier n’est pas au format exécutable et que ce fichier n’est pas un répertoire, il est supposé être un script shell et le shell l’exécute comme décrit. dans les scripts shell ".
source
c’est que les fonctions sont devenues disponibles à partir de bash sans avoir besoin de charger ou de relancer. Exemple#!/bin/bash function olakease {echo olakease;}
. Une fois que vous l'avez chargé,source file.sh
vous pouvez appeler directementolakease
depuis bash. J'aime beaucoup ça. La source exécute puis charge beaucoup de choses, le point.
est uniquement pour l'exécution et ressemble à une utilisationbash file.sh
.
a également ce comportement:. file.sh
etsource file.sh
fait exactement la même chose, y compris en conservant les fonctions définies dansfile.sh
. (Peut-être pensez-vous à./file.sh
ce qui est différent. Mais cela n'utilise pas la fonction.
intégrée; cela.
fait plutôt partie du chemin.)Oui, vous manquez quelque chose.
Je pense que vous confondez le '.' cela signifie répertoire en cours, comme dans
./testenv.sh
et le '.' cela signifiesource
(qui est une commande intégrée). Donc dans le cas où '.' signifie quesource
ce serait. ./testenv.sh
. Avoir un sens?Alors essayez ceci:
la source
./
dit exactement où se trouve le fichier, sans cela, bash examinera d'abord PATH, puis essaiera le répertoire en cours s'il ne l'a pas trouvé. Si bash est en cours d'exécution en mode POSIX et que vous ne fournissez pas de chemin d'accès au fichier (comme./
), la recherche s'effectue uniquement dans PATH et le fichier ne sera pas trouvé si le répertoire en cours n'est pas dans PATH.source
(et.
) fait va vérifier d' abord $ PATH, même si elles ne sont pas vraiment en cours d' exécution du script dans le sens habituel. Mon (ancien) commentaire était incorrect.