Para tornar o primeiro post deste blog bem simbólico, vamos falar sobre a primeira coisa que devemos colocar em um shell script: o #! (vulgarmente chamado de shebang ou hashbang).

O #! shebang serve para dizer ao kernel qual será o interpretador a ser utilizado para executar os comandos presentes no arquivo.

Quando executamos um arquivo que começa com #!, o kernel abre o arquivo e pega tudo que está escrito após o shebang até o final da linha. Em seguida ele tenta executar um comando com o conteúdo desta string adicionando como parâmetro o nome do próprio arquivo.

Portanto se você tem arquivo executável chamado meuscript.sh, contendo um shell-script e começando com #!/bin/bash, quando você executa esse arquivo o kernel vai executar /bin/bash meuscript.sh.

Nos exemplos a seguir você verá isso muito claramente.

Vamos começar com o clássico hello.sh:

#!/bin/bash
echo "Hello World!"

Quando é digitado no shell:

$ ./hello.sh

O kernel vai ver o #! e vai ler o que vem a seguir até o final da linha, neste caso /bin/bash. E então o que é executado é equivalente a você fazer isso no shell:

$ /bin/bash hello.sh

(A propósito, veja neste post porque é uma boa prática iniciar seus scripts com #!/usr/bin/env bash no lugar de #!/bin/bash)

Vejamos agora um outro exemplo usando #!/bin/cat. O nome do arquivo é hashbangcat

#!/bin/cat
Todo o conteúdo deste arquivo será
exibido quando ele for executado
(inclusive o '#!/bin/cat').

O que é lido após o hashbang: /bin/cat
Nome do arquivo: hashbangcat

Portanto será executado: /bin/cat hashbangcat

Veja:

$ ./hashbangcat
#!/bin/cat
Todo o conteúdo deste arquivo será
exibido quando ele for executado
(inclusive o '#!/bin/cat').

Agora um exemplo que deixa bastante claro que as coisas acontecem exatamente como estou dizendo. Vamos usar #!/usr/bin/echo. O seguinte arquivo se chama hashbangecho:

#!/usr/bin/echo
O conteúdo deste arquivo *não* será
exibido quando ele for executado.

Agora vamos executar esse arquivo:

$ ./hashbangecho
./hashbangecho

A saída do comando foi o nome do arquivo pois o que realmente foi executado foi /usr/bin/echo ./hashbangecho.

Se passarmos parâmetros, eles também serão repassados. Conforme veremos no exemplo a seguir.

Este arquivo se chama hashbangls.sh:

#!/bin/ls
O conteúdo aqui não importa.

Agora ele sendo executado:

$ ./hashbangls.sh
./hashbangls.sh
$ ./hashbangls.sh notfound
/bin/ls: cannot access 'notfound': No such file or directory
./hashbangls.sh
$ ./hashbangls.sh -l
-rwxr-xr-x 1 meleu meleu 41 Dec 20 14:42 ./hashbangls.sh

OK, como você deve ter percebido, isso não tem lá muita utilidade prática no dia a dia. Mas fica aí como curiosidade para você entender a necessidade de colocar um #! no início dos seus scripts.

Fontes