Saltar al contenido
01/03/2024

Shebang en Linux: qué es, cómo funciona y ejemplos en Bash y Python


El Shebang es una de esas pequeñas piezas de Linux que parecen simples, pero que esconden mucho más de lo que aparentan. Está formado por dos caracteres, #!, colocados al inicio de un script, y sirve para indicar qué intérprete debe ejecutar ese archivo.

Por ejemplo:

#!/bin/bash
echo "Hola desde Bash"

O en Python:

#!/usr/bin/env python3
print("Hola desde Python")

A simple vista parece una línea decorativa, pero no lo es. El Shebang permite que un script pueda ejecutarse directamente como si fuera un programa:

./script.sh

en lugar de tener que llamar manualmente al intérprete:

bash script.sh

La diferencia parece pequeña, pero es fundamental para entender cómo Linux ejecuta scripts, cómo funciona la automatización, cómo se crean herramientas de línea de comandos y por qué ciertos errores como bad interpreter, permission denied o /usr/bin/env: python3\r aparecen con tanta frecuencia.

En este artículo vamos a ver qué es el Shebang, cómo funciona internamente en Linux, qué ocurre en el kernel cuando ejecutas un script, cuándo usar #!/bin/bash, cuándo usar #!/usr/bin/env bash, cómo aplicarlo en Bash y Python, y cuáles son los errores más comunes.


Qué es el Shebang

Tabla del contenido

El Shebang es la primera línea de un script cuando empieza con los caracteres:

#!

Después de esos dos caracteres se indica la ruta del intérprete que debe ejecutar el archivo.

Ejemplo:

#!/bin/bash

Esto significa:

“Ejecuta este archivo usando /bin/bash como intérprete”.

Otro ejemplo:

#!/usr/bin/env python3

Esto significa:

“Busca python3 en el PATH del sistema y usa ese intérprete para ejecutar este archivo”.

El Shebang también se conoce como:

  • hashbang
  • sharp-bang
  • pound-bang
  • sha-bang
  • línea #!

En la práctica, todos esos nombres hacen referencia a lo mismo: la instrucción que le dice al sistema operativo qué programa debe interpretar el contenido del script.


Sintaxis básica del Shebang

La sintaxis general es:

#!ruta-del-intérprete [argumento-opcional]

Por ejemplo:

#!/bin/bash
#!/bin/sh
#!/usr/bin/env bash
#!/usr/bin/env python3
#!/usr/bin/perl
#!/usr/bin/env php

La línea debe estar al principio del archivo. No puede ir en la segunda línea ni después de un comentario.

Correcto:

#!/bin/bash
echo "Hola"

Incorrecto:

# Este script imprime un saludo
#!/bin/bash
echo "Hola"

En el segundo caso, el sistema no reconocerá el Shebang porque no aparece como primera línea real del archivo.


Por qué el Shebang debe ir en la primera línea

Linux no escanea todo el archivo buscando #!. Cuando intentas ejecutar un archivo, el kernel mira el inicio del archivo para decidir cómo tratarlo.

Si los dos primeros bytes son:

#!

entonces lo interpreta como un script con Shebang.

Si no aparecen ahí, el kernel no usa esa línea para resolver el intérprete.

Por eso esta línea:

#!/bin/bash

debe ser literalmente la primera línea del archivo.

Incluso una línea vacía antes del Shebang puede romper el comportamiento esperado:


#!/bin/bash
echo "Esto puede fallar si se ejecuta directamente"

Primer ejemplo: script Bash con Shebang

Crea un archivo llamado hola.sh:

nano hola.sh

Añade este contenido:

#!/bin/bash

echo "Hola desde Bash"
echo "Este script se está ejecutando con: $SHELL"

Guarda el archivo y dale permisos de ejecución:

chmod +x hola.sh

Ahora ejecútalo directamente:

./hola.sh

Salida esperada:

Hola desde Bash
Este script se está ejecutando con: /bin/bash

Aquí el Shebang permite que el sistema sepa que debe usar /bin/bash para interpretar el archivo.


Segundo ejemplo: script Python con Shebang

Crea un archivo llamado saludo.py:

nano saludo.py

Añade:

#!/usr/bin/env python3

print("Hola desde Python")

Dale permisos de ejecución:

chmod +x saludo.py

Ejecuta el archivo directamente:

./saludo.py

Salida esperada:

Hola desde Python

Sin el Shebang, el sistema no sabría por sí solo si ese archivo debe ejecutarse con Python, Bash, Perl, Ruby, PHP u otro intérprete.


Qué ocurre realmente cuando ejecutas un script en Linux

Cuando escribes:

./hola.sh

no estás ejecutando “texto”. Estás pidiendo al sistema operativo que ejecute un archivo.

De forma simplificada, ocurre esto:

Usuario ejecuta ./hola.sh
        ↓
La shell recibe el comando
        ↓
La shell llama a execve()
        ↓
El kernel abre el archivo
        ↓
El kernel lee el inicio del archivo
        ↓
Detecta los caracteres #!
        ↓
Extrae la ruta del intérprete
        ↓
Ejecuta el intérprete
        ↓
Le pasa el script como argumento
        ↓
El intérprete lee y ejecuta el contenido del script

Es decir, el script no se ejecuta “solo”. Lo ejecuta un intérprete.

Cuando el archivo empieza con:

#!/bin/bash

Linux termina ejecutando algo equivalente a:

/bin/bash ./hola.sh

Cuando empieza con:

#!/usr/bin/env python3

Linux termina ejecutando algo conceptualmente parecido a:

/usr/bin/env python3 ./saludo.py

Y luego env busca python3 en el PATH.


El papel de execve()

En Linux, una de las llamadas al sistema más importantes para entender este proceso es execve().

No necesitas usar execve() directamente en tus scripts diarios, pero entender su papel ayuda a comprender qué hace realmente el sistema.

Cuando una shell como Bash intenta ejecutar un archivo, utiliza funciones de la familia exec. A bajo nivel, Linux usa execve() para reemplazar el programa actual por otro programa.

Esto es importante: execve() no crea un nuevo proceso por sí misma. Lo que hace es reemplazar la imagen del proceso actual por un nuevo programa.

Cuando ejecutas:

./script.sh

la shell crea un proceso hijo y ese proceso hijo llama a execve() para intentar ejecutar ./script.sh.

El kernel revisa el archivo. Si es un binario ejecutable, lo carga como programa. Si es un script que empieza con #!, busca el intérprete indicado en esa línea y ejecuta ese intérprete pasándole el script como argumento.


Cómo interpreta Linux la línea #!

La lógica interna es más o menos esta:

1. El kernel intenta ejecutar el archivo.
2. Comprueba si los dos primeros caracteres son #!.
3. Si no lo son, ese manejador no aplica.
4. Si sí lo son, analiza la primera línea.
5. Extrae la ruta del intérprete.
6. Extrae un argumento opcional, si existe.
7. Reorganiza los argumentos.
8. Abre el intérprete.
9. Reinicia la ejecución usando ese intérprete.

Por ejemplo, este Shebang:

#!/bin/bash

indica que el intérprete es:

/bin/bash

Este otro:

#!/usr/bin/env bash

indica que el intérprete inicial es:

/usr/bin/env

y que bash será el argumento pasado a env.

Por eso #!/usr/bin/env bash no significa exactamente “ejecuta Bash directamente”. Significa:

“Ejecuta /usr/bin/env y pídele que encuentre bash usando el PATH”.


Diferencia entre ejecutar con Shebang y llamar al intérprete manualmente

Este punto es clave.

Supongamos que tienes este script:

#!/bin/bash

echo "Hola"

Puedes ejecutarlo de dos formas:

./script.sh

o:

bash script.sh

Cuando usas:

./script.sh

el Shebang importa. El sistema mira la primera línea y usa el intérprete indicado.

Pero cuando usas:

bash script.sh

el Shebang prácticamente no decide nada, porque ya has elegido tú el intérprete: bash.

Esto explica por qué un script puede funcionar así:

bash script.sh

pero fallar así:

./script.sh

En el primer caso, llamas explícitamente a Bash. En el segundo, dependes de tres cosas:

  1. Que el archivo tenga permisos de ejecución.
  2. Que el Shebang esté bien escrito.
  3. Que el intérprete indicado exista y pueda ejecutarse.

Permisos de ejecución: por qué necesitas chmod +x

El Shebang no sustituye los permisos de ejecución.

Puedes tener un script perfecto:

#!/bin/bash
echo "Hola"

pero si no tiene permisos de ejecución, al intentar ejecutarlo así:

./script.sh

puedes obtener:

Permission denied

Para solucionarlo:

chmod +x script.sh

Luego:

./script.sh

La idea es simple:

  • El Shebang indica con qué intérprete ejecutar el archivo.
  • Los permisos indican si el archivo puede ejecutarse.

Son dos cosas distintas.

Puedes comprobar los permisos con:

ls -l script.sh

Ejemplo:

-rwxr-xr-x 1 david david 42 jun 18 10:30 script.sh

La x indica permiso de ejecución.


#!/bin/bash vs #!/usr/bin/env bash

Una de las dudas más comunes es qué Shebang conviene usar en scripts Bash:

#!/bin/bash

o:

#!/usr/bin/env bash

Ambas opciones son válidas, pero no significan exactamente lo mismo.


Usar #!/bin/bash

Cuando usas:

#!/bin/bash

estás indicando una ruta absoluta. El sistema intentará ejecutar Bash exactamente desde:

/bin/bash

Ventajas:

  • Es explícito.
  • Es predecible.
  • No depende del PATH.
  • Es buena opción para scripts de sistema o entornos controlados.

Desventajas:

  • Bash puede estar en otra ruta en algunos sistemas.
  • Es menos flexible en entornos donde se usan versiones personalizadas de Bash.

Puedes comprobar dónde está Bash con:

which bash

o mejor:

command -v bash

Ejemplo:

/usr/bin/bash

En muchas distribuciones modernas /bin puede ser un enlace simbólico hacia /usr/bin, pero no conviene asumirlo siempre si buscas máxima portabilidad.


Usar #!/usr/bin/env bash

Cuando usas:

#!/usr/bin/env bash

estás usando env para buscar bash en el PATH.

Ventajas:

  • Es más portable entre sistemas.
  • Respeta el entorno del usuario.
  • Funciona bien cuando el intérprete está instalado en una ruta no estándar.
  • Es útil en entornos con gestores de versiones.

Desventajas:

  • Depende del PATH.
  • Puede ejecutar un intérprete inesperado si el PATH está manipulado.
  • En scripts sensibles o administrativos puede ser menos predecible.

En la práctica:

  • Para scripts personales, herramientas de desarrollo o proyectos portables: #!/usr/bin/env bash.
  • Para scripts de sistema, automatizaciones críticas o entornos cerrados: #!/bin/bash o la ruta absoluta comprobada.

#!/bin/sh vs #!/bin/bash

Otro error común es pensar que sh y bash son siempre lo mismo.

No lo son.

Este Shebang:

#!/bin/sh

indica que el script debe ejecutarse con la shell del sistema compatible con POSIX.

Este otro:

#!/bin/bash

indica que debe ejecutarse con Bash.

La diferencia importa porque Bash tiene características que no existen necesariamente en sh.

Por ejemplo, este script usa arrays de Bash:

#!/bin/bash

nombres=("Ana" "Luis" "David")
echo "${nombres[2]}"

Eso funciona en Bash, pero puede fallar si lo ejecutas con sh.

En cambio, un script POSIX más portable sería:

#!/bin/sh

nombre="David"
echo "$nombre"

Regla práctica:

  • Usa #!/bin/sh si quieres portabilidad POSIX.
  • Usa #!/bin/bash si vas a usar características específicas de Bash.
  • No uses #!/bin/sh en un script que realmente depende de Bash.

Shebang en Python: python, python3, env y entornos virtuales

En Python, el Shebang también es importante.

Opciones comunes:

#!/usr/bin/python3
#!/usr/bin/env python3

La primera usa una ruta absoluta. La segunda busca python3 en el PATH.

Para scripts de desarrollo, normalmente es preferible:

#!/usr/bin/env python3

porque funciona mejor con entornos virtuales.

Ejemplo:

#!/usr/bin/env python3

import sys

print("Ejecutable de Python:", sys.executable)
print("Versión:", sys.version)

Si activas un entorno virtual:

source .venv/bin/activate

y luego ejecutas:

./script.py

el uso de /usr/bin/env python3 permite que el sistema encuentre el python3 del entorno virtual, siempre que el PATH esté configurado correctamente.

Eso es muy útil en proyectos reales, porque evita atar el script a una ruta fija del sistema.


Tabla comparativa de Shebangs comunes

ShebangUso típicoVentajaRiesgo o limitación
#!/bin/bashScripts Bash en LinuxPredecible y directoBash debe existir en esa ruta
#!/usr/bin/env bashScripts portablesBusca Bash en el PATHDepende del entorno
#!/bin/shScripts POSIXMuy portableNo soporta todas las funciones de Bash
#!/usr/bin/python3Scripts Python en sistema fijoRuta explícitaMenos flexible con entornos virtuales
#!/usr/bin/env python3Scripts Python portablesCompatible con venv y PATHPuede usar otro Python si el PATH cambia
#!/usr/bin/env nodeScripts Node.jsÚtil con nvm/asdfDepende del PATH
#!/usr/bin/env phpScripts PHP CLIPortableDepende del PATH

Errores comunes con Shebang

El Shebang parece simple, pero muchos errores de scripts vienen de esta línea.

Veamos los más frecuentes.


Error: Permission denied

Ejemplo:

./script.sh

Salida:

bash: ./script.sh: Permission denied

Causa probable:

El archivo no tiene permisos de ejecución.

Solución:

chmod +x script.sh
./script.sh

Error: bad interpreter: No such file or directory

Ejemplo:

bad interpreter: No such file or directory

Causas posibles:

  1. La ruta del intérprete no existe.
  2. El Shebang está mal escrito.
  3. El archivo tiene saltos de línea de Windows.
  4. El intérprete no está instalado.

Ejemplo incorrecto:

#!/bin/bahs

Aquí hay un typo: bahs en lugar de bash.

Comprueba la ruta correcta:

command -v bash

Salida posible:

/usr/bin/bash

Entonces puedes usar:

#!/usr/bin/bash

o:

#!/usr/bin/env bash

Error por saltos de línea de Windows: /usr/bin/env: ‘python3\r’

Este es uno de los errores más comunes cuando editas scripts en Windows y luego los ejecutas en Linux, WSL, Docker o un servidor.

Error típico:

/usr/bin/env: ‘python3\r’: No such file or directory

El problema es el carácter \r, que viene de los saltos de línea CRLF de Windows.

Linux espera saltos de línea LF. Si el archivo tiene CRLF, el sistema puede interpretar el Shebang como:

#!/usr/bin/env python3\r

Entonces intenta buscar un programa llamado python3\r, no python3.

Soluciones:

dos2unix script.py

O con sed:

sed -i 's/\r$//' script.py

También puedes configurar tu editor para guardar archivos con formato LF.

En VS Code, por ejemplo, puedes cambiar CRLF a LF desde la barra inferior.


Error: Exec format error

Puedes ver algo como:

cannot execute: Exec format error

Esto puede pasar si el archivo no tiene un formato ejecutable reconocido y tampoco tiene un Shebang válido.

Ejemplo problemático:

echo "Hola"

Si guardas eso como script y haces:

chmod +x script
./script

puede fallar porque no hay una primera línea que indique qué intérprete debe usarse.

Solución:

#!/bin/bash
echo "Hola"

Error: Shebang en la segunda línea

Incorrecto:

# Script de prueba
#!/bin/bash

echo "Hola"

Correcto:

#!/bin/bash
# Script de prueba

echo "Hola"

El Shebang debe ser la primera línea real del archivo.


Error: usar Bash pero declarar sh

Ejemplo:

#!/bin/sh

nombres=("Ana" "Luis" "David")
echo "${nombres[0]}"

Este script probablemente fallará porque los arrays no forman parte de sh POSIX.

Solución:

#!/bin/bash

nombres=("Ana" "Luis" "David")
echo "${nombres[0]}"

La regla es sencilla: el Shebang debe declarar el intérprete que tu script realmente necesita.


Limitaciones del Shebang

Aunque el Shebang es muy útil, tiene limitaciones.

1. Debe estar en la primera línea

No puede ir precedido por comentarios, espacios raros o líneas vacías.

2. El intérprete debe existir

Si escribes:

#!/opt/custom/bash

pero esa ruta no existe, el script fallará.

3. Hay límites de longitud

La línea del Shebang no puede ser arbitrariamente larga. En Linux moderno, el texto procesado después de #! tiene un límite. Por eso conviene mantener esta línea simple y clara.

4. Los argumentos múltiples no siempre son portables

Este Shebang puede parecer razonable:

#!/usr/bin/env python3 -O

pero en muchos sistemas no se interpreta como dos argumentos separados. Puede tratarse como un único argumento completo, provocando errores.

Para varios argumentos con env, en sistemas que soportan GNU env, puedes usar -S:

#!/usr/bin/env -S python3 -O

Aun así, si buscas portabilidad máxima, evita Shebangs demasiado complejos.


Qué hace /usr/bin/env en un Shebang

env es un programa que puede ejecutar otro comando en un entorno determinado.

Cuando escribes:

#!/usr/bin/env bash

el sistema ejecuta:

/usr/bin/env bash ./script.sh

Luego env busca bash usando la variable PATH.

Puedes ver tu PATH con:

echo "$PATH"

Ejemplo:

/usr/local/bin:/usr/bin:/bin

Si bash está en alguna de esas rutas, env lo encontrará.

Esto permite que el mismo script funcione en sistemas donde Bash puede estar en rutas diferentes.


Cuándo usar /usr/bin/env

Usa /usr/bin/env cuando quieras que el sistema encuentre el intérprete según el entorno actual.

Ejemplos recomendados:

#!/usr/bin/env bash
#!/usr/bin/env python3
#!/usr/bin/env node

Casos típicos:

  • scripts de desarrollo
  • herramientas CLI
  • proyectos compartidos entre sistemas
  • entornos virtuales de Python
  • gestores de versiones como pyenv, nvm o asdf
  • scripts que pueden ejecutarse en Linux, macOS o WSL

Cuándo evitar /usr/bin/env

Evita /usr/bin/env cuando necesites control absoluto sobre el intérprete.

Por ejemplo:

  • scripts de administración del sistema
  • scripts ejecutados por root
  • automatizaciones críticas
  • entornos de producción muy controlados
  • scripts donde el PATH puede ser manipulado

En esos casos, una ruta absoluta puede ser más segura:

#!/bin/bash

o:

#!/usr/bin/python3

La razón es que /usr/bin/env depende del PATH. Si el PATH apunta primero a un directorio inseguro, podría ejecutarse un binario inesperado.

Ejemplo de riesgo conceptual:

PATH="/tmp:$PATH"

Si alguien coloca un ejecutable llamado python3 en /tmp, un script con:

#!/usr/bin/env python3

podría terminar ejecutando ese binario antes que el Python real del sistema.

En scripts personales no suele ser un problema grave, pero en scripts privilegiados o sensibles sí importa.


Shebang, PATH y seguridad

La variable PATH define dónde busca el sistema los comandos cuando no se proporciona una ruta absoluta.

Por ejemplo, cuando escribes:

ls

la shell busca ls dentro de las rutas listadas en PATH.

Cuando usas:

#!/usr/bin/env bash

también estás delegando esa búsqueda al entorno.

Esto es cómodo, pero debes entender la implicación:

  • Ruta absoluta: más control.
  • /usr/bin/env: más flexibilidad.
  • Flexibilidad sin control puede abrir la puerta a errores o riesgos.

Buenas prácticas:

#!/bin/bash
set -euo pipefail

Y en scripts sensibles, definir un PATH seguro:

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH

Shebang y WSL

En WSL, el Shebang funciona como en Linux porque estás ejecutando un entorno Linux sobre Windows.

El problema más común no es WSL en sí, sino los archivos editados desde Windows con saltos de línea CRLF.

Ejemplo de error:

/usr/bin/env: ‘bash\r’: No such file or directory

Solución:

dos2unix script.sh

O configurar Git para manejar saltos de línea correctamente.

Para proyectos que se ejecutan en Linux/WSL, suele ser recomendable usar LF.

Puedes configurar Git así:

git config --global core.autocrlf input

Esto ayuda a evitar que los scripts terminen con saltos de línea incompatibles.


Shebang y Docker

En Docker, el Shebang también importa.

Ejemplo de script de entrada:

#!/bin/sh
set -e

echo "Iniciando contenedor..."
exec "$@"

Si lo usas como ENTRYPOINT, necesitas que tenga permisos de ejecución:

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

Errores comunes en Docker:

permission denied

Solución:

RUN chmod +x /entrypoint.sh

Otro error:

exec /entrypoint.sh: no such file or directory

Aunque el archivo exista, puede deberse a CRLF. Convierte el archivo a LF.

También debes tener cuidado con la imagen base. En Alpine Linux, por ejemplo, normalmente tienes /bin/sh, pero no necesariamente /bin/bash.

Este Shebang puede fallar:

#!/bin/bash

si Bash no está instalado.

En Alpine, para scripts simples, suele ser mejor:

#!/bin/sh

O instalar Bash explícitamente si lo necesitas.


Buenas prácticas al escribir Shebangs

1. Usa el intérprete correcto

No declares sh si estás usando Bash.

Mal:

#!/bin/sh
array=("uno" "dos")

Bien:

#!/bin/bash
array=("uno" "dos")

2. Usa /usr/bin/env para scripts portables

Para herramientas de desarrollo:

#!/usr/bin/env bash

Para Python:

#!/usr/bin/env python3

3. Usa rutas absolutas en scripts críticos

Para scripts de sistema:

#!/bin/bash

o la ruta real comprobada:

#!/usr/bin/bash

4. Añade permisos de ejecución

chmod +x script.sh

5. Evita CRLF

Convierte archivos editados en Windows:

dos2unix script.sh

O:

sed -i 's/\r$//' script.sh

6. Comprueba el intérprete

command -v bash
command -v python3
command -v node

7. Mantén el Shebang simple

Evita líneas demasiado largas o con muchos argumentos.

Mejor:

#!/usr/bin/env python3

que:

#!/usr/bin/env python3 -O -B -X dev

Si necesitas opciones complejas, plantéate moverlas al propio script o a la forma de invocarlo.


Laboratorio práctico: probando el Shebang paso a paso

Vamos a crear tres scripts para entender cuándo importa el Shebang.

Script 1: Bash correcto

cat > demo-bash.sh <<'EOF'
#!/bin/bash

echo "Ejecutado con Bash"
echo "Versión de Bash: $BASH_VERSION"
EOF

Permisos:

chmod +x demo-bash.sh

Ejecución:

./demo-bash.sh

Script 2: Bash ejecutado con sh

Ahora ejecuta el mismo script con sh:

sh demo-bash.sh

Puede que algunas partes funcionen, pero si el script usa características exclusivas de Bash, fallará.

Ejemplo:

cat > arrays.sh <<'EOF'
#!/bin/bash

nombres=("Ana" "Luis" "David")
echo "${nombres[2]}"
EOF

chmod +x arrays.sh
./arrays.sh
sh arrays.sh

La ejecución directa usará Bash por el Shebang. La ejecución con sh arrays.sh ignora la intención del Shebang y fuerza el uso de sh.


Script 3: Python portable

cat > demo-python.py <<'EOF'
#!/usr/bin/env python3

import sys

print("Hola desde Python")
print(sys.executable)
EOF

chmod +x demo-python.py
./demo-python.py

Este ejemplo te muestra qué ejecutable de Python está usando realmente el script.


Cómo depurar problemas con Shebang

Cuando un script falla, sigue este checklist.

1. Ver la primera línea

head -n 1 script.sh

2. Ver caracteres ocultos

cat -A script.sh | head

Si ves algo como:

#!/usr/bin/env bash^M$

tienes saltos de línea CRLF.

3. Comprobar permisos

ls -l script.sh

4. Comprobar intérprete

command -v bash
command -v python3

5. Ejecutar explícitamente

bash script.sh
python3 script.py

Si funciona explícitamente pero no con ./script, el problema probablemente está en:

  • permisos
  • Shebang
  • saltos de línea
  • ruta del intérprete

Historia breve del Shebang

El Shebang forma parte de la tradición Unix. Su función nació de una necesidad práctica: permitir que los scripts de texto pudieran ejecutarse de forma similar a los binarios.

Sin esta convención, el usuario tendría que escribir siempre:

sh script.sh
python3 script.py
perl script.pl

Con el Shebang, el sistema puede delegar la ejecución al intérprete correcto automáticamente.

Esto convirtió a los scripts en ciudadanos de primera clase dentro del ecosistema Unix: pequeños programas ejecutables, automatizables y combinables con otras herramientas.

Por eso el Shebang sigue siendo tan importante hoy en Linux, macOS, BSD, WSL, Docker y servidores de producción.


Preguntas frecuentes sobre Shebang

¿El Shebang es obligatorio?

No siempre.

Si ejecutas un script así:

bash script.sh

no necesitas Shebang porque ya estás indicando el intérprete.

Pero si quieres ejecutarlo directamente:

./script.sh

entonces sí necesitas un Shebang válido y permisos de ejecución.


¿Qué significa #!/bin/bash?

Significa que el archivo debe ejecutarse usando Bash desde la ruta:

/bin/bash

Es una ruta absoluta al intérprete.


¿Qué significa #!/usr/bin/env bash?

Significa que el sistema debe ejecutar /usr/bin/env, y que env debe buscar bash en el PATH.

Es más portable, pero depende del entorno.


¿Qué es mejor: /bin/bash o /usr/bin/env bash?

Depende del caso.

Para scripts de sistema o entornos controlados:

#!/bin/bash

Para scripts portables o de desarrollo:

#!/usr/bin/env bash

¿Qué pasa si no pongo Shebang?

Si ejecutas el archivo directamente, puede fallar porque el sistema no sabe qué intérprete usar.

Si lo ejecutas pasando el archivo a un intérprete, sí puede funcionar:

bash script.sh
python3 script.py

¿Puedo usar Shebang en Windows?

Windows no usa Shebang de forma nativa como Linux o Unix. Sin embargo, herramientas como Git Bash, WSL, Cygwin o MSYS2 sí pueden reconocerlo dentro de sus entornos.

En WSL funciona como en Linux.


¿Por qué aparece /usr/bin/env: python3\r?

Porque el archivo probablemente tiene saltos de línea de Windows, conocidos como CRLF.

Convierte el archivo a formato Unix:

dos2unix script.py

¿El Shebang afecta si ejecuto python3 script.py?

No de forma relevante.

Cuando ejecutas:

python3 script.py

ya estás eligiendo el intérprete manualmente. El Shebang importa principalmente cuando ejecutas el archivo directamente:

./script.py

¿Puedo pasar argumentos en el Shebang?

Sí, pero con limitaciones.

Ejemplo simple:

#!/bin/bash -e

Sin embargo, los argumentos múltiples pueden no comportarse igual en todos los sistemas.

Para varios argumentos con GNU env, puede usarse:

#!/usr/bin/env -S python3 -O

Pero no conviene abusar de esto si buscas portabilidad.


¿Qué Shebang debo usar para Python?

Para scripts portables:

#!/usr/bin/env python3

Para scripts de sistema donde quieres usar una ruta concreta:

#!/usr/bin/python3

Conclusión

El Shebang es mucho más que una primera línea curiosa en un script. Es el mecanismo que permite que Linux sepa qué intérprete debe usar para ejecutar un archivo de texto como si fuera un programa.

Cuando escribes:

#!/bin/bash

estás atando el script a Bash en una ruta concreta.

Cuando escribes:

#!/usr/bin/env bash

estás delegando la búsqueda de Bash al PATH.

Cuando escribes:

#!/usr/bin/env python3

estás haciendo que un script Python pueda ejecutarse directamente y adaptarse mejor a entornos virtuales o configuraciones portables.

Dominar el Shebang implica entender varios conceptos importantes de Linux:

  • permisos de ejecución
  • rutas absolutas
  • variable PATH
  • intérpretes
  • llamadas exec
  • diferencias entre sh y bash
  • saltos de línea LF y CRLF
  • seguridad en scripts
  • automatización real

Por eso, aunque solo sean dos caracteres, #! es una puerta de entrada a cómo Linux ejecuta scripts por dentro.

Si estás aprendiendo Bash, Python, automatización o administración de sistemas, entender bien el Shebang no es un detalle menor: es una base que te evitará errores y te ayudará a escribir scripts más portables, seguros y profesionales.