Um documento aqui é uma forma de redirecionamento. Em seus comandos, você redireciona para o comando cat
e, em seguida, tenta usar a saída como um comando em uma substituição de comando.
-
$i
será expandido quando o conteúdo do documento here for formado. Isso acontece muito antes de o loop no documento ser executado. Se a variáveli
não estiver definida, ela será expandida para uma sequência vazia. Você pode optar por citar o documento here (citando o primeiroEOF
como'EOF'
ou\EOF
) para que nenhuma expansão seja feita nele ou para explicitamente escapar do$
as\$
para protegê-lo da expansão. - O conteúdo do documento here será interpretado como uma única string com linhas delimitadas de nova linha. Ele não passará pelo reconhecimento usual de token e por outras etapas envolvidas na análise de comandos comuns, mas será dividido em palavras individuais, pois a substituição do comando não é citada. Em particular,
for
não será reconhecido como uma palavra-chave do shell. É por isso que seu primeiro exemplo falho falha. Para reavaliar a string, você teria queeval
it, que iria reavaliar a string como a shell teria feito se tivesse sido dada na linha de comando. -
O último exemplo seria expandido para
bash
seguido por várias palavras. A primeira palavra éfor
, portanto,bash
esperaria executar um script chamadofor
no diretório atual, mas falha ao fazer isso. -
Em todos os exemplos,
bash
deve também ter reclamado que o documento here não foi terminado corretamente (desde que a última linha éEOF)
com um parêntese direito à direita, nãoEOF
) , dizendo algo comobash: warning: here-document at line 1 delimited by end-of-file (wanted 'EOF')
a menos que você esteja usando uma versão
bash
mais antiga, como a padrão no macOS.
Em vez disso, essa seria uma melhor escolha de ações, pois evita a conversão de código em uma string que precisa ser reinterpretada e, em vez disso, fornece o documento como um script de shell diretamente para um interpretador de shell.
bash <<'END_SCRIPT'
for i in *; do
printf 'Filename: "%s"\n' "$i"
done
END_SCRIPT
O primeiro dos seus exemplos funciona porque é um comando simples.