
Eu tenho um script simples envolvendo um for
loop do bash que estou tentando fazer funcionar no zsh. Eu presumi que o shebang garantiria que um shell compatível com POSIX fosse usado (no meu sistema que tenho /bin/sh -> dash*
), para que não houvesse problemas.
Script MWE onde ITEMS
está na verdade a saída de um comando que lista pacotes, por exemplo 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
Esta é a saída quando tento executar o script em 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
Quando eu executo em um terminal bash, ele funciona bem. Acho que entendi mal como o shebang é interpretado por zsh
? Alguém pode me explicar como deve ser usado para que quando eu executo source scratch.sh
ou . ./scratch.sh
tenha a mesma saída como se tivesse executado sh scratch.sh
? Eu sei que poderia modificar meu script de loop for para ser compatível zsh
e bash
nativo, mas quero usá-lo, /bin/sh -> dash
então estou sempre usando um shell compatível com posix e não preciso me preocupar com bashisms ou zshisms.
Peço desculpas se esta é uma pergunta básica, pesquisei zsh
e posix
shebang, mas não encontrei uma pergunta semelhante.
Responder1
O shebang só tem efeito se você executar o script diretamentesem especificar como executá-lo; isto é, com algo como ./scratch.sh
ou /path/to/scratch.sh
ou colocando-o em um diretório no seu PATH
e apenas usando scratch.sh
.
Se você executá-lo usando algum outro comando, isso controla o que é feito com ele (substituindo o shebang). Se você usar bash scratch.sh
, ele roda em bash
; se você usar zsh scratch.sh
, ele roda em zsh
; se você usar sh
, ele roda em tudo o sh
que estiver no seu sistema ( dash
no seu caso específico).
Se você usar source scratch.sh
ou . scratch.sh
, ele será executado ema casca atual, seja lá o que é. Esse é todo o propósito dos comandos .
e source
. E, novamente, a coisa é ignorada aqui.
Responder2
Você não pode fazer isso. . script
ou source script
simplesmente inclui script
, ele não cria um shell padrão ou não padrão separado para fazer isso. Quanto às coisas, porzsh
(quando vocêfonteum roteiro em vez deexecutarisso) eles são apenas comentários.
Você pode instruir zsh
(tentar) emular temporariamente um shell padrão. YMMV.
emulate sh -c '. ./scratch.sh'
emulate which_sh -c str
avaliará str
com a emulação especificada temporariamente em vigor e, mais importante, fará com que ela "grude" em quaisquer funções definidas durante a avaliação do str
, fazendo com que o modo de emulação seja ativado automaticamente durante sua execução.