Cuando escribes python3 en la terminal y la shell lo ejecuta, no está buscando ese nombre en todo el disco. Está recorriendo una lista de directorios llamada PATH — una variable de entorno que contiene rutas separadas por dos puntos — y ejecuta el primer archivo que encuentra con ese nombre. Si escribes python y obtienes command not found, el problema casi siempre es este: el ejecutable no está en ninguno de esos directorios, o existe con un nombre distinto.
El PATH típico en Debian tiene este aspecto:
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
La shell los recorre de izquierda a derecha y se detiene en la primera coincidencia. Eso significa que el orden importa: si tienes dos versiones del mismo programa en directorios distintos, gana la que aparece primero.
Para saber exactamente qué va a ejecutar la shell cuando escribes un nombre, tienes tres herramientas: which, type y command -v. No son intercambiables — cada una responde a una pregunta ligeramente distinta, y confundirlas lleva a diagnósticos incorrectos.
which es un programa externo (un binario en /usr/bin/which) que busca en el PATH y devuelve la ruta del ejecutable. Solo ve archivos en el sistema de ficheros; no conoce los alias ni las funciones que has definido en tu sesión de bash. Si has creado alias ls='ls --color=auto', which ls te devolverá /usr/bin/ls — correcto como ruta, pero incompleto como diagnóstico, porque eso no es lo que bash ejecuta cuando escribes ls.
type es un built-in de bash, es decir, no es un programa externo sino un comando que bash ejecuta directamente desde su propio código. Por eso tiene acceso a toda la información interna de la shell: sabe si algo es un alias, una función definida en tu .bashrc, un built-in de bash como cd, o un ejecutable en el disco. Es la herramienta correcta para diagnóstico interactivo.
command -v es la versión portátil especificada por POSIX. Funciona igual en sh, dash, bash y cualquier shell compatible. Cuando escribes scripts que deben correr en entornos donde no sabes qué shell está disponible — un hook de git, un script de instalación, un contenedor mínimo — command -v es lo que debes usar.
Si te equivocas de herramienta, el diagnóstico falla silenciosamente: which te dirá que un comando existe, pero la shell ejecutará en realidad otra cosa (el alias o la función); o usarás type en un script sh y obtendrás un error porque ese shell no lo implementa.
Ejemplo completo
# Situación: tienes varios "python" en el sistema y quieres saber
# exactamente qué ejecuta tu shell en cada caso.
# 1. Ver el PATH actual, directorios separados por ":"
echo "$PATH"
# 2. which: busca solo ejecutables en el PATH, ignora alias y funciones
which python3
which python # probablemente falla en Debian — python2 no está por defecto
# 3. type: built-in de bash, muestra TODO: alias, funciones, built-ins, ejecutables
type python3 # → python3 is /usr/bin/python3
type ls # → ls is aliased to `ls --color=auto` (si tienes el alias)
type cd # → cd is a shell builtin
type ll # → ll is aliased to `ls -l --color=auto` (si existe el alias)
# 4. type -a: muestra TODAS las coincidencias, no solo la primera
# Útil cuando sospechas que hay varios python3 en distintos directorios
type -a python3
# 5. command -v: versión POSIX, la correcta para scripts
command -v python3 # → /usr/bin/python3
command -v cd # → cd (para built-ins solo devuelve el nombre)
# 6. Uso típico en un script portable: comprobar si un comando existe
# La redirección a /dev/null suprime la salida; solo nos interesa el código de salida
if command -v git > /dev/null 2>&1; then
echo "git está disponible"
else
echo "git no está instalado"
fi
# 7. Crear un alias temporal y ver la diferencia entre which y type
alias python='python3'
which python # → /usr/bin/python (si existe) o nada — NO ve el alias
type python # → python is aliased to 'python3' — SÍ ve el alias
Qué está pasando en cada paso
El echo "$PATH" del principio no es decorativo — antes de diagnosticar cualquier problema con un ejecutable, necesitas saber qué directorios está consultando tu shell. Si /usr/local/bin aparece antes que /usr/bin, un ejecutable instalado manualmente ahí tendrá prioridad sobre el del sistema.
El which python del paso 2 probablemente no devuelve nada en Debian Bookworm porque el paquete python2 no está instalado por defecto y python3 no crea un enlace simbólico llamado python a menos que instales el paquete python-is-python3. Este es exactamente el problema descrito al principio: el binario existe, pero con otro nombre.
La diferencia entre type ls y which ls en el paso 3 es el caso más frecuente de confusión. El .bashrc de Debian incluye alias ls='ls --color=auto' por defecto, así que which ls y type ls devuelven información distinta — ambas verdaderas, pero respondiendo preguntas distintas.
type -a python3 del paso 4 es especialmente útil cuando usas entornos virtuales de Python o tienes versiones instaladas en /usr/local/bin por compilación manual. Te muestra toda la cadena de candidatos en orden de prioridad, no solo el ganador.
El bloque if command -v git del paso 6 es el patrón correcto para scripts. Usar which aquí es un error habitual: en algunos sistemas which devuelve un código de salida 0 incluso cuando no encuentra el comando, lo que rompe la lógica del if. command -v se comporta de forma consistente según POSIX: código 0 si lo encuentra, código distinto de 0 si no.
El paso 7 demuestra por qué which no sirve para diagnóstico completo en sesiones interactivas. Después de definir alias python='python3', which python sigue sin encontrarlo (porque busca un archivo llamado python en el PATH, no el alias), mientras que type python muestra exactamente lo que bash va a hacer. Si estás depurando por qué un comando se comporta de forma inesperada en tu terminal, type es siempre el punto de partida correcto.
N° 14