Llamar un script con ./bla.sh vs. bla.sh

11

¿Alguien puede explicarme qué hace el shell en los dos ejemplos A) y B) a continuación? Obviamente se comporta de manera diferente, pero no puedo descubrir por qué la salida es diferente.

Ejemplo:
Tengamos un script en nuestro directorio actual nombrado bla.shcon un solo comando:
echo ${0##/*} hello

A)
Comenzó como: ./bla.sh
da:./bla.sh hello

B)
Comenzó como: . bla.sh
da:-bash hello

Como uso esto en una secuencia de comandos, la segunda salida (debido a "-" delante de -bash) mata el comando. Por supuesto, un simple --antes de la ${...}ayuda, pero me encantaría entender qué causa la salida en primer lugar.
Me encanta bash Y vi [m]. Pero yo divago…

Lobo
fuente

Respuestas:

22
./bla.sh

Aquí, el comando es ./bla.sh. Esto hace que el shell busque un ejecutable nombrado bla.shen el directorio actual, luego le pide al kernel que lo ejecute como un programa normal, en un proceso separado del shell. (No importa si bla.shes un bashscript, uno perlo pythonuno, o un binario compilado).


. bla.sh

Aquí, el comando es .(aka source), un comando incorporado de su shell. Hace que el shell busque un archivo nombrado bla.shen la ruta del sistema ($ PATH) e interprete los contenidos como si los hubiera escrito usted; todo esto se realiza en el mismo proceso que el shell en sí (y, por lo tanto, puede afectar el estado interno del shell).

Por supuesto, esto solo funciona cuando bla.shcontiene comandos para el bashshell (si ese es el que está usando actualmente), no funcionará para perlscripts o cualquier otra cosa.

(Esto se explica en help .y help sourcetambién).


Como .y ./son cosas completamente diferentes (un comando vs parte de una ruta de acceso), que se pueden combinar, por supuesto - usando . ./bla.shharía "fuente" un archivo bla.shen el directorio actual.


Por lo general, es mejor usar el ./bla.shmétodo. Solo ~/.bashrc, ~/.profiley tales archivos generalmente se obtienen, porque se supone que modifican el entorno actual.

usuario1686
fuente
3
Además, si cambia el entorno bash en bla.sh, estos cambios se tienen en cuenta después. bla.sh pero no después de ./bla.sh. esto es porque . bla.sh se ejecuta en el contexto del bash actual, mientras que ./bla.sh se ejecuta como un subproceso.
mouviciel
1
Ver también mywiki.wooledge.org/BashFAQ/060 para algunos ejemplos. Tenga en cuenta que sourcees un alias bash para ., no al contrario, y sourceno funcionará en otros shells.
mrucci
7

./<cmd>ejecutará el <cmd>programa que reside en el directorio actual en un nuevo proceso (bifurcado). Tiene que ser ejecutable. Y también legible comienza con #!.

. <cmd>hará que su shell actual ejecute el script de shell <cmd>que reside en su $PATHdirectorio actual o en el proceso actual del shell. Tiene que ser legible. Es un alias para el comando de shell source.

kmkaplan
fuente
-1 . <cmd>buscará el programa $PATHy, si no se encuentra ENTONCES, buscará en el directorio actual.
dogbane
@ Dogbane Correcto, corrigí esto.
kmkaplan
FWIW, no todos los shells buscarán en cwd fragmentos de origen. zsh (al menos con la configuración que tengo) requiere. ./cmd
bstpierre
1
@bstpierre Esto parece ser un terreno en movimiento. La referencia POSIX que tengo dice que "el shell usará la ruta de búsqueda especificada por PATH" y "Algunas implementaciones más antiguas buscaron el archivo actual en el archivo, incluso si el valor de PATH no lo permitía".
kmkaplan
1

./cmd usa una ruta explícita ( ./- directorio actual) al ejecutable. Y no es necesario que comience con #!.

. cmd- (aka source) - comando bash incorporado. Una diferencia visible de la ejecución sourcees que puede establecer / modificar la variable de entorno del shell actual.

Leonid Volnitsky
fuente
más precisamente, sourcees un alias de bash-only para .(que es estándar)
user1686
Tienes razón. Fijo.
Leonid Volnitsky