O melhor que eu tenho é o "shebang de duas linhas" que é realmente um script poliglota (Bourne shell / Node.js):
#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"
console.log('Hello world!');
A primeira linha é, obviamente, uma casca de Bourne. Node.js ignora qualquer shebang que encontrar, então este é um arquivo javascript válido no que diz respeito ao Node.js.
A segunda linha chama o shell no-op :
com o argumento //
e, em seguida, executa nodejs
ou node
com o nome desse arquivo como parâmetro. command -v
é usado em vez de which
para portabilidade. A sintaxe de substituição de comandos $(...)
não é estritamente Bourne, portanto, opte por backticks se você executar isso nos anos 80.
O Node.js apenas avalia a string ':'
, que é como um no-op, e o resto da linha é analisada como um comentário.
O restante do arquivo é simplesmente um javascript antigo. O subshell é encerrado após a conclusão da exec
na segunda linha, portanto, o restante do arquivo nunca é lido pelo shell.
Obrigado a xavierm02 pela inspiração e a todos os comentadores por informações adicionais!