Cuando necesitas saber dónde está un archivo o un comando en el sistema, tienes cuatro herramientas distintas y cada una responde una pregunta ligeramente diferente. Usarlas sin entender esa diferencia lleva a confusión: buscas con which y no encuentras nada, pero el comando existe. O usas locate y el archivo que acabas de crear no aparece. Vamos a ver exactamente qué hace cada una y cuándo elegirla.
locate no recorre el disco cuando lo ejecutas: consulta una base de datos pre-indexada que mantiene el sistema en /var/lib/plocate/plocate.db (o /var/lib/mlocate/mlocate.db en instalaciones más antiguas). Eso lo hace casi instantáneo incluso en discos con millones de archivos. El precio es que esa base de datos se actualiza por cron una vez al día, así que cualquier archivo creado después de la última ejecución de updatedb sencillamente no existe para locate. Si acabas de crear un archivo y no aparece, ejecuta updatedb como root para refrescar manualmente.
En Debian Bookworm el paquete recomendado es plocate, que reemplaza al antiguo mlocate. Es más rápido, usa menos memoria y el comando sigue siendo locate. Si instalas mlocate y plocate a la vez, entran en conflicto porque ambos quieren controlar updatedb; quédate con plocate.
which es completamente diferente: recorre tu variable de entorno PATH de izquierda a derecha y devuelve la ruta completa del primer ejecutable que encuentra con ese nombre. Solo ve ejecutables en el sistema de archivos. No ve alias, no ve funciones de shell, no ve built-ins de bash. Si tienes alias ls='ls --color=auto' y ejecutas which ls, te devuelve /usr/bin/ls, que es técnicamente correcto pero incompleto para entender qué pasará realmente cuando escribas ls.
whereis amplía un poco la búsqueda: además del binario, intenta localizar el archivo fuente y la página de manual asociados. No usa PATH sino una lista de directorios estándar codificada. Es útil para ver rápidamente si un comando tiene documentación instalada o de dónde viene su man page, pero tampoco ve alias ni funciones.
type es un built-in de bash (no un programa externo), y es la herramienta más completa para diagnóstico interactivo. Entiende toda la jerarquía de resolución de bash: primero alias, luego funciones, luego built-ins, finalmente ejecutables en PATH. Cuando escribes un comando en la terminal, bash sigue exactamente ese orden. type te muestra lo que bash realmente va a ejecutar. Para scripts que necesitan ser portables entre shells, command -v es la alternativa estándar POSIX, porque type se comporta diferente en sh, zsh o fish.
Si usas which para diagnosticar por qué un comando se comporta de forma inesperada y which dice que está en /usr/bin/python3, podrías asumir que todo está bien, cuando en realidad hay una función de shell que intercepta esa llamada. type te lo habría mostrado de inmediato.
# Asegurarnos de que plocate está instalado
sudo apt install plocate
# locate busca en la base de datos: rápido pero puede estar desactualizado
locate python3
# Creamos un archivo de prueba para demostrar la limitación
touch /tmp/archivo_nuevo_$(date +%s).txt
# locate NO encuentra ese archivo todavía porque la BD no se ha actualizado
locate archivo_nuevo
# Actualizamos manualmente la base de datos (requiere root)
sudo updatedb
# Ahora sí aparece
locate archivo_nuevo
# -----------------------------------------------------------------
# which: solo ve ejecutables en PATH, nada más
which python3
# Salida típica: /usr/bin/python3
# Definimos un alias para el ejemplo
alias python3='echo "alias interceptado"'
# which sigue devolviendo el ejecutable — no ve el alias
which python3
# whereis: binario + fuente + man page (búsqueda en dirs estándar)
whereis python3
# Salida típica: python3: /usr/bin/python3 /usr/lib/python3 /usr/share/man/man1/python3.1.gz
# -----------------------------------------------------------------
# type: refleja exactamente lo que bash va a ejecutar
# Con el alias activo, type lo muestra primero
type python3
# Salida: python3 is aliased to `echo "alias interceptado"'
# Eliminamos el alias para ver el ejecutable
unalias python3
type python3
# Salida: python3 is /usr/bin/python3
# type -a muestra TODAS las coincidencias en orden de precedencia
type -a python3
# Comprobamos un built-in de bash
type cd
# Salida: cd is a shell builtin
# Comprobamos algo que no existe — el código de salida será 1
type comando_inexistente
echo "Código de salida: $?"
# -----------------------------------------------------------------
# En scripts: command -v en lugar de type (POSIX portable)
if command -v python3 > /dev/null 2>&1; then
echo "python3 está disponible en PATH"
else
echo "python3 no encontrado"
fi
locate archivo_nuevo falla la primera vez no porque el archivo no exista, sino porque el índice no sabe de él todavía. Después de sudo updatedb, el índice se reconstruye leyendo el sistema de archivos real, y la segunda búsqueda ya lo encuentra. Ese comportamiento es el que más sorprende a gente nueva en la herramienta.
La secuencia con el alias demuestra exactamente por qué which python3 te puede mentir en un diagnóstico. Mientras el alias está activo, ejecutar python3 en esa sesión nunca llega al binario de /usr/bin. which no lo sabe. type sí, porque consulta la misma tabla interna que bash usa para resolver comandos. type -a va más lejos: muestra todas las coincidencias apiladas en orden de prioridad, útil cuando sospechas que hay un ejecutable en un directorio de PATH que está siendo tapado por otro.
La línea type cd confirma que cd no es ningún ejecutable en disco: es un built-in que bash implementa internamente. Si intentaras which cd, en algunos sistemas no devolvería nada o devolvería una ruta que en realidad no existe como programa independiente ejecutable.
command -v en el bloque final redirige tanto stdout como stderr a /dev/null porque en un script solo te importa el código de salida: 0 si el comando existe en PATH, distinto de 0 si no. Es la forma correcta de hacer esta comprobación en scripts que no sabes en qué shell van a correr. type en /bin/sh de Debian (que es dash, no bash) se comporta diferente y no aceptará las mismas opciones.
N° 46