
Tengo un script simple que involucra un for
bucle desde bash que estoy tratando de hacer funcionar en zsh. Supuse que el shebang garantizaría que se usara un shell compatible con POSIX (en mi sistema que tengo /bin/sh -> dash*
) para que no hubiera ningún problema.
Script MWE donde ITEMS
en realidad es la salida de un comando que enumera paquetes, por ejemplo ITEMS=$(pip freeze)
:
#!/bin/sh
# ITEMS=$(pip freeze) # Example of useful command
ITEMS="Item1
Item2
Item3" # Dummy variable for testing
for ITEM in $ITEMS; do
echo $ITEM
echo Complete
done
Este es el resultado cuando intento ejecutar el script en zsh
:
$ source scratch.sh
Item1
Item2
Item3
Complete # Undesired
$ . ./scratch.sh
Item1
Item2
Item3
Complete # Undesired
$ bash scratch.sh
Item1
Complete
Item2
Complete
Item3
Complete # Desired
$ sh scratch.sh
Item1
Complete
Item2
Complete
Item3
Complete # Desired
Cuando lo ejecuto en una terminal bash, funciona bien. Creo que he entendido mal cómo interpreta el tinglado zsh
. ¿Alguien puede explicarme cómo se debe usar de manera que cuando ejecuto source scratch.sh
tenga . ./scratch.sh
el mismo resultado que si lo hubiera ejecutado sh scratch.sh
? Sé que podría modificar mi script de bucle for para que sea compatible zsh
y bash
de forma nativa, pero quiero usarlo, /bin/sh -> dash
así que siempre estoy usando un shell compatible con posix y no tengo que preocuparme por bashisms o zshisms.
Disculpas si esta es una pregunta básica, busqué zsh
y posix
shebang pero no encontré una pregunta similar.
Respuesta1
El shebang solo tiene efecto si ejecuta el script directamentesin especificar como ejecutarlo; es decir, con algo como ./scratch.sh
o /path/to/scratch.sh
o colocándolo en un directorio en tu PATH
y simplemente usando scratch.sh
.
Si lo ejecuta usando algún otro comando, eso controla lo que se hace con él (anulando el shebang). Si lo usa bash scratch.sh
, se ejecuta bash
; si lo usas zsh scratch.sh
, se ejecuta zsh
; si usa sh
, se ejecuta en lo que sea que sh
esté en su sistema ( dash
en su caso específico).
Si usa source scratch.sh
o . scratch.sh
, se ejecuta enel caparazón actual, sea lo que sea. Ese es el propósito de los comandos .
and source
. Y nuevamente, aquí se ignora el asunto.
Respuesta2
No puedes hacer eso. . script
o source script
simplemente incluye script
, no bifurca un shell estándar o no estándar separado para hacerlo. En cuanto a shebangs, porque zsh
(cuandofuenteun guión en lugar deejecutarit) son solo comentarios.
Sin embargo, puedes indicar zsh
(intentar) emular temporalmente un shell estándar. YMMV.
emulate sh -c '. ./scratch.sh'
emulate which_sh -c str
se evaluará str
con la emulación especificada temporalmente en vigor y, lo que es más importante, hará que se "pegue" a cualquier función definida durante la evaluación de str
, lo que provocará que el modo de emulación se active automáticamente durante su ejecución.