Não há garantia de que o shell irá ou não carregar todo o documento aqui na memória. Enormes scripts não são típicos, então este não é um caso que os implementadores de shell possam otimizar. É até indesejável que todo o script não seja carregado na memória antes que a execução comece a executá-lo, mas todas as shells comuns são executadas antes do carregamento completo, o que significa que elas executam lixo se o arquivo de script for modificado durante a execução. >
Experimentalmente, no Debian jessie, dash, bash, mksh e zsh carregam um documento de 130kB aqui na memória, enquanto o ksh93 copia 64kB sem alocar mais memória. Então, a única maneira de usar um documento aqui que não cabe na memória é garantir que seu script seja executado com ksh93 (ou talvez ksh88) - e antes de fazer isso, por favor, assegure-se que este é o caso de outras versões, verificou que o comportamento é o mesmo com todas as compilações de ksh.
O que você pode fazer de forma mais portável é colocar todos os dados no final do script e usar tail -c $offset
para extrair a carga útil. Ele funciona na prática porque nenhum dos shells usuais carrega o script completamente na memória antes de executá-lo. Esse método tem a vantagem de que a carga útil pode ser binária - os documentos aqui não podem conter a cadeia de caracteres final-de-heredoc ou bytes nulos.
Se o seu script é constante, você pode codificar o deslocamento da carga útil. Se não for, você pode colocar um marcador distinto no final do script e usar o awk para determinar sua localização:
offset=$(awk '{offset += length($0) + 1}
$0 == "# payload starts here (do not remove this magic comment)" {
print offset; exit
}')
…
tail -c "$offset" <"$0" — …
…
# payload starts here (do not remove this magic comment)
Se você tiver mais de uma carga útil, precisará de um comando mais complexo para extraí-las. Tenha em atenção que head -c
não existe em todas as variantes unix. Você pode usar dd ibs=1 count=$bytes
para obter o mesmo efeito, mas pode ser muito lento, pois muitas implementações de dd
copiarão um byte de cada vez. O que eu recomendaria é acrescentar um arquivo tar e extrair arquivos pelo nome dele.