`find`: búsqueda de archivos por criterios en el filesystem

find recorre el árbol de directorios en tiempo real —no consulta ningún índice— y evalúa cada entrada contra los criterios que le pases. Eso explica dos cosas a la vez: por qué es lento en árboles enormes (visita cada nodo), y por qué siempre devuelve resultados frescos, sin el desfase que tiene locate cuando su base de datos lleva días sin actualizarse.

La sintaxis sigue siempre el mismo orden: punto de inicio, criterios (predicados que filtran), acción (qué hacer con lo que pasa el filtro). Si omites la acción, aplica -print por defecto. Si omites el punto de inicio en algunas implementaciones obtienes un error; en Debian, sé explícito y pon siempre el directorio.

Úsalo cuando necesites localizar archivos por características que el nombre no refleja: permisos mal configurados, archivos modificados en las últimas horas, logs que han crecido demasiado, binarios con el bit SUID activado. No es la herramienta para buscar contenido dentro de archivos —eso es grep— sino para encontrar los archivos en sí mismos basándote en sus metadatos del filesystem.

Lo que rompes si te equivocas: -delete no pregunta, no va a la papelera y no tiene undo. Un -delete con un criterio mal escrito sobre / puede arruinar un sistema en segundos. La práctica correcta es siempre construir el comando sin -delete, verificar la lista de archivos que imprime, y solo entonces sustituir -print por -delete. Lo mismo aplica a -exec: si el comando que ejecutas es destructivo, el mismo principio.

# Escenario: auditoría de un servidor web.
# Queremos limpiar logs antiguos, detectar permisos incorrectos
# y verificar qué archivos PHP se han tocado recientemente.

# 1. Logs de más de 30 días y más de 10 MB — primero solo listamos
find /var/log/nginx -type f -name "*.log" -mtime +30 -size +10M -print

# 2. Confirmada la lista, los comprimimos en batch con -exec ... +
# El "+" agrupa los archivos y lanza gzip una sola vez con todos ellos,
# mucho más eficiente que "\;" que lanza un proceso por archivo.
find /var/log/nginx -type f -name "*.log" -mtime +30 -size +10M \
  -exec gzip -9 {} +

# 3. Archivos PHP modificados en los últimos 2 días (posible intrusión
# o despliegue reciente); -iname ignora mayúsculas/minúsculas
find /var/www/html -type f -iname "*.php" -mtime -2 -print

# 4. Archivos más nuevos que el último despliegue conocido.
# Útil cuando no sabes la fecha exacta pero tienes un archivo de referencia.
find /var/www/html -type f -newer /var/www/html/index.php -print

# 5. Permisos incorrectos: archivos de configuración que no deberían
# ser world-readable. -perm -o+r significa "tiene activo el bit de lectura
# para others", sea cual sea el resto de la máscara.
find /etc/nginx -type f -perm -o+r -print

# 6. Binarios con SUID fuera de los directorios habituales — señal de alerta.
# -perm -4000 detecta el bit SUID independientemente del resto de permisos.
# -not -path evita los directorios donde el SUID es legítimo y esperado.
find / -xdev -type f -perm -4000 \
  -not -path "/usr/bin/*" \
  -not -path "/usr/sbin/*" \
  -not -path "/bin/*" \
  -print 2>/dev/null

# 7. Combinar condiciones con -or explícito (los paréntesis necesitan escape
# o comillas para que bash no los interprete como subshell).
# Buscamos archivos temporales con dos extensiones posibles.
find /tmp -type f \( -name "*.tmp" -or -name "*.swp" \) -mtime +1 -delete

El criterio -xdev del paso 6 le dice a find que no cruce fronteras de sistema de archivos. Sin él, entraría en /proc, /sys y cualquier mount que haya, generando ruido y ralentizando todo. En una búsqueda de SUID sobre / siempre lo necesitas.

La diferencia entre -exec {} \; y -exec {} + no es cosmética. Con \;, find lanza un proceso nuevo por cada archivo encontrado: si hay 800 logs, ejecuta gzip 800 veces. Con +, acumula los paths y los pasa todos como argumentos a un único proceso, igual que haría xargs. El paso 2 del ejemplo usa + precisamente por eso; si el comando que necesitas no acepta múltiples argumentos (algunos scripts caseros, por ejemplo), entonces sí toca usar \;.

El filtro -mtime -2 del paso 3 significa “modificado hace menos de 2×24 horas”. Los valores de -mtime son siempre en días completos de 24 horas, lo que puede sorprender: un archivo tocado hace 25 horas tiene -mtime de 1, no de 0. Si necesitas granularidad de minutos, usa -mmin con la misma lógica de signos.

Para la búsqueda por permisos, -perm 644 exige exactamente esos permisos. -perm -644 (con guion) exige que al menos esos bits estén activos, ignorando los demás. -perm /644 (con barra) actúa como OR: basta con que alguno de esos bits esté activo. En el paso 5 usamos -perm -o+r con notación simbólica, que es más legible que recordar qué posición octal corresponde a qué bit.

fd (fd-find en los repositorios de Debian) es una alternativa que merece mención: ignora directorios ocultos y entradas de .gitignore por defecto, tiene sintaxis más corta y colorea la salida. Para búsquedas interactivas rápidas en proyectos de desarrollo es más cómodo. Para scripts de auditoría o mantenimiento del sistema, find sigue siendo la elección correcta: está en cualquier sistema base, su comportamiento es predecible y su sintaxis es la misma desde hace décadas.

45

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio