La principale différence est qu'ils sont exécutés dans un processus différent.
Donc, si vous source
un fichier foo
qui fait un cd
, le sourcing shell (par exemple votre shell interactif dans le terminal) est affecté (et son répertoire courant va changer)
Si vous exécutez sh foo
le cd
n'affecte pas le sourcing shell, seulement le sh
fraîchement créé processus exécutant foo
Lisez le Guide de création de scripts avancés pour Bash.
Comme d'autres l'ont mentionné, lorsque vous exécutez sh test.sh
, toute modification test.sh
les modifications apportées à votre environnement shell ne persisteront pas après la fin du processus.
Cependant, notez également que tout élément de votre environnement qui n'est pas exporté (par exemple, les variables, les alias et les fonctions shell) ne sera pas disponible pour le code dans test.sh
lorsqu'il est exécuté en tant que sous-processus (c'est-à-dire avec sh test.sh
).
Par exemple :
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
Exemple 2 :
[email protected]:~$ cat test.sh
#!/bin/sh
cd /etc
[email protected]:~$ sh test.sh
[email protected]:~$ pwd
/home/savoury
[email protected]:~$ source test.sh
[email protected]:/etc$ pwd
/etc
[email protected]:/etc$
Lorsque vous appelez le source
ou .
(l'un est un alias de l'autre. source
cmd pas POSIX - une sorte de bashisme ), vous chargez et exécutez un script shell dans le courant processus shell . Vous pouvez donc
- lire les variables définies dans le script sourcé,
- utiliser les fonctions qui y sont définies.
- et même exécuter des forks et/ou des sous-processus si le script le fait.
Lorsque vous appelez le sh
, vous lancez un fork (sous-processus ou enfant ) qui exécute une nouvelle session de /bin/sh
(qui est souvent un lien symbolique vers bash
). Dans ce cas, les variables d'environnement définies par le sous-script seraient supprimées lorsque le sous-script se terminerait.
Attention :sh
pourrait être un lien symbolique vers un autre coque.
Exemple pratique
Par exemple, si vous souhaitez modifier le répertoire de travail actuel d'une manière spécifique, vous ne pourriez pas faire
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
Cela ne fera pas ce que vous attendez :
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
car répertoire de travail actuel fait partie de l'environnement et myCd2Doc.sh
s'exécuterait dans un sous-shell .
Mais :
$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
Jetez un œil à mycd
fonction!! (Avec complétion bash basée sur Associative Array ).
Niveau d'exécution $SHLVL
$ cd /tmp
printf %b '\43\41/bin/bash\necho This is level \44SHLVL.\n' >qlvl.sh
$ bash qlvl.sh
This is level 2.
$ source qlvl.sh
This is level 1.
Récursivité (lorsqu'un script s'exécute à partir de lui-même)
$ cat <<eoqlvl2 >qlvl2.sh
#!/bin/bash
export startLevel recursionLimit=5
echo This is level $SHLVL started:${startLevel:=$SHLVL}.
(( SHLVL < recursionLimit )) && ./qlvl2.sh
eoqlvl2
$ chmod +x qlvl2.sh
$ ./qlvl2.sh
This is level 2 started:2.
This is level 3 started:2.
This is level 4 started:2.
This is level 5 started:2.
$ source qlv2.sh
This is level 1 started:1.
This is level 2 started:1.
This is level 3 started:1.
This is level 4 started:1.
This is level 5 started:1.
Un peu plus loin
$ sed '$a ps --sid $SID fw' qlvl.sh >qlvl3.sh
$ chmod +x qlvl3.sh
$ export SID
$ read SID < <(ps ho sid $$)
$ echo $SID $$
8983 8983
( PID actuel ($$
==identifiant de processus ) sont le même identifiant que SID (identifiant de session ). Ce n'est pas toujours vrai.)
$ ./qlvl3.sh
This is level 2.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10266 pts/10 S+ 0:00 \_ /bin/bash ./qlvl3.sh
10267 pts/10 R+ 0:00 \_ ps --sid 8983 fw
$ . qlvl3.sh
This is level 1.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10428 pts/10 R+ 0:00 \_ ps --sid 8983 fw
Point .
est un alias de source
. Donc, la seule différence entre deux commandes est slash
remplacé par space
.
Et une finale tester :
$ printf %b '\43\41/bin/bash\necho Ending this.\nsle' \
'ep 1;exit 0\n' >finalTest.sh
$ bash finalTest.sh
Ending this.
$ source finalTest.sh
Ending this.
... Vous remarquerez peut-être un différent comportement entre les deux syntaxes.;-)