La principal diferencia es que se ejecutan en un proceso diferente.
Así que si source
un archivo foo
que hace un cd
, el shell de abastecimiento (por ejemplo, su shell interactivo en la terminal) se ve afectado (y su directorio actual cambiará)
Si ejecuta sh foo
el cd
no afecta el shell de abastecimiento, solo el sh
recién creado proceso ejecutando foo
Lea la Guía avanzada de secuencias de comandos de Bash.
Como han mencionado otros, cuando ejecutas sh test.sh
, cualquier cambio que test.sh
hace a su entorno de shell no persistirá después de que el proceso haya finalizado.
Sin embargo, también tenga en cuenta que cualquier elemento de su entorno que no se exporte (por ejemplo, variables, alias y funciones de shell) no estará disponible para el código en test.sh
cuando se ejecuta como un subproceso (es decir, con sh test.sh
).
Por ejemplo:
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
Ejemplo 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$
Cuando llamas al source
o .
(uno es un alias del otro. source
cmd no POSIX - una especie de bashism ), carga y ejecuta un script de shell en el actual proceso de shell . Entonces puedes
- leer las variables establecidas en el script de origen,
- usar funciones definidas dentro de él.
- e incluso ejecutar bifurcaciones y/o subprocesos si el script hace esto.
Cuando llamas al sh
, inicias una bifurcación (subproceso o hijo ) que ejecuta una nueva sesión de /bin/sh
(que suele ser un enlace simbólico a bash
). En este caso, las variables de entorno establecidas por el subíndice se descartarían cuando el subíndice termine.
Precaución :sh
podría ser un enlace simbólico a otro concha.
Muestra práctica
Por ejemplo, si desea cambiar el directorio de trabajo actual de una manera específica, no podrías hacer
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
Esto no hará lo que esperas:
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
porque directorio de trabajo actual es parte del entorno y myCd2Doc.sh
se ejecutaría en una subcapa .
Pero:
$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
Echa un vistazo a mycd
¡¡función!! (Con bash completado basado en Asociative Array ).
Nivel de ejecución $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.
Recursividad (cuando un script se ejecuta desde sí mismo)
$ 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 poco más
$ 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 actual ($$
==Id. de proceso ) son el mismo identificador que SID (ID de sesión ). No siempre es cierto.)
$ ./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
Punto .
es un alias de source
. Entonces, la única diferencia entre dos comandos es slash
reemplazado por space
.
Y una final prueba:
$ 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.
... Puede notar un diferente comportamiento entre las dos sintaxis.;-)