15%

Ahorra 15%<\/span> en todos los servicios de hosting

Pon a prueba tus habilidades y obtén Descuento<\/span> en cualquier plan de hosting

Usa el código:

Skills
Comenzar
08.10.2024

El comando `which` en Linux: Guía técnica completa con ejemplos

El comando `which` en Linux localiza la ruta absoluta de un ejecutable escaneando los directorios listados en la variable de entorno `PATH` y devolviendo la primera coincidencia que encuentra. Es una utilidad adyacente a POSIX utilizada diariamente por administradores de sistemas, desarrolladores e ingenieros DevOps para verificar ubicaciones de binarios, auditar entornos de ejecución y depurar conflictos relacionados con PATH.

Cuando ejecutas `which python3`, el shell no busca en todo el sistema de archivos — recorre únicamente la lista de directorios delimitada por dos puntos almacenada en `$PATH`, de izquierda a derecha, y se detiene en la primera coincidencia. Este comportamiento es tanto su mayor fortaleza como su limitación más importante a comprender.

Sintaxis Básica

“`bash

which [options] command_name [command_name …]

“`

  • `[options]` — Indicadores opcionales que modifican el comportamiento de la salida (detallados a continuación).
  • `command_name` — Uno o más nombres de ejecutables que deseas localizar.

Cómo Funciona Internamente `which`

Cuando invocas `which`, lee el valor actual de la variable de entorno `PATH`, la divide en delimitadores `:` e itera a través de cada directorio en orden. Para cada directorio, comprueba si existe un archivo que coincida con el nombre del comando y tiene el bit ejecutable establecido (permiso `x`). La primera coincidencia se imprime en la salida estándar.

Esto significa que `which` depende completamente del estado en tiempo de ejecución de `$PATH`. Si tu `PATH` está mal configurado — por ejemplo, un directorio personalizado aparece después de `/usr/bin` en lugar de antes — `which` reflejará exactamente esa mala configuración, que es precisamente por qué es útil para depuración.

Para inspeccionar tu `PATH` actual:

“`bash

echo $PATH

Example output:

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

“`

Casos de Uso Principales y Ejemplos

Ejemplo 1: Localizar un Único Ejecutable

El uso más fundamental es encontrar dónde reside un binario:

“`bash

which python3

“`

“`

/usr/bin/python3

“`

Esto confirma que cuando escribes `python3`, el sistema ejecuta `/usr/bin/python3`. Si has compilado una versión personalizada y la has colocado en `/opt/python3.12/bin/`, pero ese directorio no está en `PATH`, `which` no lo encontrará.

Ejemplo 2: Consultar Múltiples Comandos en una Sola Ejecución

Puedes pasar múltiples nombres de comandos en una sola invocación, lo cual es eficiente al auditar un entorno de compilación:

“`bash

which python3 gcc git curl wget

“`

“`

/usr/bin/python3

/usr/bin/gcc

/usr/bin/git

/usr/bin/curl

/usr/bin/usr/bin/wget

“`

Esto es particularmente útil en scripts de validación de pipelines CI/CD, donde necesitas confirmar que todas las herramientas requeridas están presentes antes de que comience una compilación.

Ejemplo 3: Descubrir Todas las Instancias con `-a`

El indicador `-a` instruye a `which` a continuar buscando después de la primera coincidencia e informar de cada instancia encontrada en todos los directorios de `PATH`:

“`bash

which -a python3

“`

“`

/usr/bin/python3

/usr/local/bin/python3

“`

Esto es crítico en entornos donde están instaladas múltiples versiones de Python — por ejemplo, un Python del sistema en `/usr/bin/python3` y una versión gestionada por pyenv en `/usr/local/bin/python3`. El binario que aparece primero en `PATH` es el que se ejecuta. Si la versión incorrecta está activa, esta salida te indica exactamente dónde se origina el conflicto.

Caso límite del mundo real: En servidores que ejecutan tanto un Node.js empaquetado por la distribución como un Node.js gestionado por nvm, `which -a node` frecuentemente revela dos o tres rutas en conflicto. Resolver esto requiere reordenar las entradas de `PATH` en `.bashrc` o `.zshrc`, no reinstalar el software.

Ejemplo 4: Comportamiento de Resolución de Alias

El comportamiento de `which` con alias depende en gran medida del shell y de la implementación específica de `which` instalada en el sistema.

En muchas distribuciones Linux, `which` es un binario externo independiente (no un built-in del shell), por lo que no tiene acceso a la tabla de alias del shell actual. Sin embargo, en sistemas donde `which` está implementado como una función o alias del shell (común en configuraciones de zsh), puede resolver alias:

“`bash

alias ls='ls –color=auto'

which ls

“`

En un sistema zsh con `which` basado en funciones:

“`

ls: aliased to ls –color=auto

“`

En un sistema bash con el binario externo `which`:

“`

/bin/ls

“`

Esta inconsistencia es una fuente de confusión bien conocida y es una de las principales razones por las que los administradores experimentados prefieren `type` o `command -v` en scripts (discutido a continuación).

Ejemplo 5: Usar `which` en Lógica Condicional de Scripts

Un patrón común en scripts de shell es usar `which` para verificar una dependencia antes de continuar:

“`bash

if ! which docker > /dev/null 2>&1; then

echo "Docker is not installed or not in PATH. Aborting."

exit 1

fi

“`

Sin embargo, el enfoque más portable y compatible con POSIX para scripts es `command -v`:

“`bash

if ! command -v docker > /dev/null 2>&1; then

echo "Docker not found."

exit 1

fi

“`

La distinción importa al escribir scripts destinados a ejecutarse en múltiples distribuciones o shells.

`which` vs. `type` vs. `command -v`: Una Comparación Técnica

Estas tres herramientas abordan necesidades superpuestas pero distintas. Elegir la incorrecta para el trabajo conduce a errores sutiles, especialmente en scripts de shell.

Característica`which``type``command -v`
Localiza binarios externos
Resuelve alias del shellDepende de la implementaciónSí (siempre)Sí (siempre)
Resuelve funciones del shellNo
Identifica built-ins del shellNo
Compatible con POSIXNo
Funciona de forma fiable en scriptsArriesgadoArriesgado (built-in de bash)Recomendado
Formato de salidaSolo rutaCadena descriptivaRuta o definición
Busca en todas las entradas de PATH (equivalente a `-a`)Sí (con `-a`)Sí (con `-a`)No
Binario externo (no un built-in)No (built-in)No (built-in)

Orientación práctica:

  • Usa `which` de forma interactiva en la terminal cuando necesites una búsqueda rápida de ruta.
  • Usa `type -a` cuando quieras ver todas las formas que toma un comando (alias, función, built-in y binario).
  • Usa `command -v` en scripts de shell en producción para portabilidad POSIX.

`type` en Acción

“`bash

type -a python3

“`

“`

python3 is /usr/bin/python3

python3 is /usr/local/bin/python3

“`

“`bash

type ls

“`

“`

ls is aliased to `ls –color=auto'

“`

`command -v` en Acción

“`bash

command -v git

“`

“`

/usr/bin/git

“`

“`bash

command -v ll

“`

“`

ll: aliased to ls -alF

“`

Escenarios Prácticos de Depuración

Depurar una Versión Incorrecta de Python

Un desarrollador informa que `python3 –version` devuelve `3.9.x` pero instalaron `3.11` mediante una compilación personalizada. La secuencia de diagnóstico:

“`bash

which python3 # Shows the first match

which -a python3 # Shows all matches

echo $PATH # Reveals directory ordering

ls -la /usr/local/bin/python3 # Checks if the custom build is symlinked correctly

“`

La solución casi siempre es un enlace simbólico faltante o un problema de ordenación de `PATH` en el archivo de inicialización del shell.

Diagnosticar un Comando Faltante Después de la Instalación

Si `which curl` no devuelve ninguna salida, el binario no está instalado o está instalado en un directorio que no es `PATH`. Distingue entre estos casos:

“`bash

which curl # No output = not in PATH

find /usr -name curl -type f 2>/dev/null # Search for the binary outside PATH

apt list –installed 2>/dev/null | grep curl # Check package manager

“`

Verificar Rutas de Herramientas Antes del Despliegue

Al configurar un nuevo entorno de VPS Hosting, una lista de verificación estándar previa al despliegue debería incluir ejecutar `which -a` contra cada binario crítico del que depende tu aplicación. Esto detecta la deriva del entorno entre desarrollo, staging y producción antes de que cause fallos en tiempo de ejecución.

Limitaciones Conocidas de `which`

Comprender estas limitaciones evita diagnósticos erróneos en entornos complejos:

  • Alcance solo de `PATH`: `which` es ciego a cualquier ejecutable que no sea accesible a través de `$PATH`. Las herramientas instaladas en directorios locales del usuario como `~/.local/bin` solo se encontrarán si ese directorio está en `PATH`.
  • Sin conocimiento de built-ins del shell: Comandos como `cd`, `echo`, `alias` y `source` son built-ins del shell. `which cd` no devolverá nada o devolverá una ruta a un binario externo `cd` que rara vez se usa, dando un resultado engañoso.
  • Tablas de alias específicas del shell: `which` como binario externo no puede leer la tabla de alias del shell que lo invoca. Esto lo hace poco fiable para la introspección de alias en bash.
  • Transparencia de enlaces simbólicos: `which` informa la ruta del enlace simbólico, no el destino resuelto. Si `/usr/bin/python3` es un enlace simbólico a `/usr/bin/python3.11`, `which python3` muestra `/usr/bin/python3`. Usa `readlink -f $(which python3)` para resolver la cadena completa.
  • Contexto de `sudo`: Ejecutar un comando con `sudo` usa el `PATH` de root, que puede diferir significativamente del `PATH` de tu usuario. `which node` como usuario regular puede devolver una ruta diferente a `sudo which node`.

Patrones Avanzados

Resolver la Cadena Completa de Enlaces Simbólicos

“`bash

readlink -f $(which python3)

Output: /usr/bin/python3.11

“`

Verificar Permisos de Ejecución Junto con la Ruta

“`bash

ls -la $(which nginx)

Output: -rwxr-xr-x 1 root root 1234567 Jan 10 2024 /usr/sbin/nginx

“`

Combinar con `xargs` para Inspección por Lotes

“`bash

echo "python3 gcc git" | xargs -n1 which

“`

Usar en Scripts de Validación de Entorno

En un Servidor Dedicado que ejecuta una pila de aplicaciones compleja, un script de validación de inicio podría verse así:

“`bash

#!/bin/bash

REQUIRED_BINS="nginx php-fpm mysql redis-cli composer"

MISSING=0

for bin in $REQUIRED_BINS; do

if ! command -v "$bin" > /dev/null 2>&1; then

echo "MISSING: $bin"

MISSING=$((MISSING + 1))

else

echo "OK: $bin -> $(which $bin)"

fi

done

[ "$MISSING" -gt 0 ] && exit 1

exit 0

“`

Notas sobre el Comportamiento Específico del Shell

El comportamiento de `which` no es uniforme en todos los entornos Linux:

  • Bash: `which` es típicamente un binario externo (`/usr/bin/which`). No ve los alias o funciones de bash a menos que estén exportados.
  • Zsh: Muchas configuraciones de zsh incluyen `which` como una función built-in del shell que sí resuelve alias y funciones, haciendo su salida más rica pero también diferente del comportamiento de bash.
  • Fish shell: Fish tiene su propio equivalente de `which` integrado, y su sistema de alias (llamado `functions`) se maneja de forma diferente.
  • Entornos Alpine Linux / BusyBox: La utilidad `which` es proporcionada por BusyBox y puede tener un conjunto de características reducido en comparación con el paquete GNU `which`.

Esta variabilidad es especialmente relevante al gestionar aplicaciones en contenedores o configurar Paneles de Control VPS donde el shell subyacente puede diferir de tu entorno de desarrollo local.

Consideraciones de Seguridad

En entornos sensibles a la seguridad, `which` puede usarse como una herramienta de auditoría ligera:

  • Verificar que los binarios privilegiados como `sudo`, `su` o `passwd` se resuelvan a las rutas del sistema esperadas y no a directorios con permisos de escritura para el usuario que aparecen antes en `PATH`.
  • Detectar intentos de secuestro de PATH: si `which ls` devuelve `/home/user/bin/ls` en lugar de `/bin/ls`, puede haberse inyectado un binario malicioso.

“`bash

Audit critical system binaries

for cmd in sudo su passwd ssh scp; do

echo "$cmd -> $(which $cmd)"

done

“`

Este es un paso estándar al endurecer un servidor que alojará Certificados SSL o manejará terminación TLS sensible, donde la integridad de los binarios no es negociable.

Al gestionar entornos de Hosting Web Compartido con múltiples usuarios, verificar que los directorios con permisos de escritura para el usuario no aparezcan antes que los directorios del sistema en el `PATH` de ningún usuario es un control de seguridad importante.

Matriz de Decisión: Cuándo Usar Qué Herramienta

EscenarioHerramienta Recomendada
Búsqueda rápida de ruta de forma interactiva`which`
Script: verificar si existe un comando`command -v`
Identificar si un comando es un alias o función`type`
Encontrar todas las instancias en PATH`which -a` o `type -a`
Resolver enlaces simbólicos al binario final`readlink -f $(which …)`
Auditar secuestro de PATH`which` + inspección manual de PATH
Scripts portables entre shells`command -v`

Conclusiones Técnicas Clave

  • `which` busca en `$PATH` de izquierda a derecha y devuelve la primera coincidencia ejecutable — el orden de las entradas de `PATH` determina directamente qué binario se ejecuta.
  • El indicador `-a` es esencial cuando coexisten múltiples versiones de una herramienta; nunca asumas que solo existe una instancia sin verificarlo.
  • No uses `which` en scripts de shell en producción — usa `command -v` para cumplimiento POSIX y comportamiento consistente entre bash, dash y zsh.
  • `which` no puede ver built-ins del shell, funciones o alias definidos en la sesión de shell actual cuando se ejecuta como binario externo.
  • Siempre complementa un resultado de `which` con `readlink -f` cuando hay enlaces simbólicos involucrados para identificar el binario real que se está ejecutando.
  • En entornos multiusuario o en contenedores, `PATH` difiere entre usuarios y entre contextos `sudo` y no-`sudo` — verifica siempre en el contexto correcto.
  • El secuestro de PATH mediante directorios con permisos de escritura para el usuario antepuestos a `$PATH` es un vector de ataque real; `which` es una herramienta de auditoría rápida de primera línea contra él.

Preguntas Frecuentes

¿Cuál es la diferencia entre `which` y `whereis`?

`which` busca solo en `$PATH` para ejecutables. `whereis` busca en un conjunto más amplio de directorios del sistema predefinidos para el binario, su página de manual y sus archivos fuente simultáneamente. Usa `whereis` cuando necesites localizar documentación o fuente junto con el binario.

¿Por qué `which cd` no devuelve nada?

`cd` es un built-in del shell, no un ejecutable externo. Dado que `which` solo escanea `$PATH` en busca de archivos con permiso de ejecución, no puede encontrar comandos built-in. Usa `type cd` en su lugar, que informará correctamente `cd is a shell builtin`.

¿Puede `which` decirme qué versión de un programa está instalada?

No. `which` solo devuelve la ruta. Para obtener la versión, canaliza el resultado: `$(which python3) –version` o simplemente `python3 –version`. La ruta de `which` te ayuda a confirmar que estás consultando el binario correcto.

¿Por qué `which python3` devuelve un resultado diferente cuando uso `sudo`?

`sudo` ejecuta comandos con el entorno de root, incluido el `PATH` de root, que típicamente es más restrictivo que el `PATH` de un usuario regular. Directorios como `~/.local/bin` o rutas de nvm/pyenv añadidas al `.bashrc` de un usuario están ausentes del `PATH` de root. Prueba siempre con `sudo which python3` por separado al depurar ejecución con privilegios elevados.

¿Está disponible `which` en macOS?

Sí, macOS incluye `which` como parte de su entorno de usuario derivado de BSD. Sin embargo, la versión de macOS no admite el indicador `-a` en todas las versiones anteriores. En macOS moderno con Homebrew, es posible que tengas instalado el GNU `which` junto con la versión del sistema. Usa `type -a which` en macOS para ver qué implementación está activa.

15%

Ahorra 15%<\/span> en todos los servicios de hosting

Pon a prueba tus habilidades y obtén Descuento<\/span> en cualquier plan de hosting

Usa el código:

Skills
Comenzar