Quando cat não recebe um nome de arquivo na linha de comando (ou se o nome do arquivo é apenas - ), ele passa a ler a entrada padrão.
Isso significa que com
cat <<END
something something
END
cat notará que não foi fornecido um nome de arquivo e continuará lendo o documento here, que está chegando em seu fluxo de entrada padrão.
Você pode obter cat para ler a partir de sua entrada padrão e de um arquivo com
cat - filename <<END
something something
END
Isso fará com que o conteúdo do documento here seja concatenado com o conteúdo de filename . Se a ordem dos argumentos fosse filename - , então essa seria a ordem em que os dados também seriam concatenados.
Observe que - não é especial para o shell de nenhuma maneira e é interpretado como "entrada padrão" especificamente pelo utilitário cat (e alguns outros). Se você tiver um arquivo real chamado - em que precisa executar cat , use cat ./- , ou seja, especifique o nome do arquivo com um caminho.
Para todos os efeitos, você pode pensar em alimentar um aqui-documento diretamente em um utilitário como uma forma abreviada de criar um arquivo temporário e depois invocar o utilitário com aquele anexado ao fluxo de entrada padrão:
printf 'some contents' >tmpfile
utility <tmpfile
rm -f tmpfile
Aqui, os documentos podem não ser realmente implementados dessa forma (pode ser um FIFO (pipe nomeado)), mas isso não é uma maneira totalmente incorreta de pensar sobre isso.
Lendo as fontes bash , parece que esse shell específico implementa here-documents criando um arquivo temporário usando a função de biblioteca mkstemp() , se estiver disponível, caso contrário, ele tentará criar um nome de arquivo aleatório para gravar. O conteúdo do documento é então gravado nesse arquivo e os dados são fornecidos na entrada padrão do que está lendo, como se viesse de um arquivo, redirecionado com < . Veja redir.c e lib/sh/tmpfile.c na distribuição da fonte bash .