Sí, los shells, y bashen particular, tienen cuidado de leer el archivo de una línea a la vez, por lo que funciona igual que cuando lo usa de forma interactiva.
Notará que cuando el archivo no se puede buscar (como una tubería), bashincluso lee un byte a la vez para asegurarse de no leer más allá del \ncarácter. Cuando se puede buscar el archivo, se optimiza leyendo bloques completos a la vez, pero se vuelve a buscar después de \n.
Eso significa que puedes hacer cosas como:
bash << \EOF
read var
var's content
echo "$var"
EOF
O escriba guiones que se actualicen a sí mismos. Lo que no podría hacer si no le brindara esa garantía.
Ahora, es raro que desee hacer cosas así y, como descubrió, esa característica tiende a interferir con más frecuencia de lo que es útil.
Para evitarlo, puede intentar asegurarse de no modificar el archivo en el lugar (por ejemplo, modificar una copia y mover la copia en su lugar (como sed -io perl -piy algunos editores lo hacen, por ejemplo)).
O podrías escribir tu guión como:
{
sleep 20
echo test
}; exit
(tenga en cuenta que es importante que exitesté en la misma línea que }; aunque también podría ponerlo dentro de los corchetes justo antes del cierre).
o:
main() {
sleep 20
echo test
}
main "$@"; exit
El shell necesitará leer el script hasta exitantes de comenzar a hacer algo. Eso asegura que el shell no volverá a leer el script.
Eso significa que todo el script se almacenará en la memoria.
Eso también puede afectar el análisis del script.
Por ejemplo, en bash:
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
Daría salida a ese U + 00E9 codificado en UTF-8. Sin embargo, si lo cambia a:
{
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
}
El \ue9se expandirá en el juego de caracteres que estaba vigente en el momento en que se analizó el comando, que en este caso es antes de queexport se ejecute el comando.
También tenga en cuenta que si se usa el comando sourceaka ., con algunos shells, tendrá el mismo tipo de problema para los archivos de origen.
Sin bashembargo, ese no es el caso de cuyo sourcecomando lee el archivo completamente antes de interpretarlo. Si escribe bashespecíficamente, podría hacer uso de eso, agregando al comienzo del script:
if [[ ! $already_sourced ]]; then
already_sourced=1
source "$0"; exit
fi
(Sin embargo, no me basaría en eso, ya que podría imaginar que las versiones futuras de bashpodrían cambiar ese comportamiento que actualmente puede verse como una limitación (bash y AT&T ksh son los únicos shells similares a POSIX que se comportan así hasta donde se sabe) y el already_sourcedtruco es un poco frágil, ya que supone que la variable no está en el entorno, sin mencionar que afecta el contenido de la variable BASH_SOURCE)