system onlinepath: /guias/linux/buscar-archivos-y-texto-con-find-y-grep/mode: knowledge_baselocal:
Linux y sistemas · Nivel inicial

Cómo buscar archivos y texto utilizando find y grep

find localiza archivos por sus atributos y grep busca dentro del contenido: cómo se usa cada uno de verdad, con ejemplos reales de cada opción, y por qué combinarlos con una tubería es donde aparece toda la potencia.

14 min de lectura▣ Actualizada el ◇ Por Underc0de
Respuesta rápida

find y grep resuelven problemas distintos y se complementan. find recorre un árbol de directorios y filtra por los metadatos de cada entrada: nombre, tipo, fecha de modificación, tamaño. grep lee el contenido de los archivos y filtra por un patrón de texto o una expresión regular. Ninguno reemplaza al otro: find no mira qué hay escrito adentro de un archivo, y grep no filtra por fecha ni por tamaño. La potencia real aparece al combinarlos con una tubería, del tipo find ... -print0 | xargs -0 grep ..., el patrón que evita que un nombre de archivo con espacios rompa todo el proceso.

Ver índice de contenidos
  1. 01¿Qué diferencia hay entre find y grep?
  2. 02Cómo buscar archivos con find
  3. 03Acciones de find: -exec {} \; frente a {} + y -delete
  4. 04El error más común: espacios, -print0 y xargs -0
  5. 05Cómo buscar texto con grep
  6. 06BRE, ERE y PCRE: qué cambia de verdad
  7. 07Combinar find y grep con una tubería
  8. 08Errores frecuentes
  9. 09Preguntas frecuentes
  10. 10Fuentes

¿Qué diferencia hay entre find y grep?

En una terminal —la interfaz de texto donde se escriben comandos, uno por línea— find y grep están entre los comandos que más se usan para ubicar algo entre miles de archivos, y aparecen en cualquier repaso de comandos útiles de Linux. Pero apuntan a preguntas distintas, y confundirlas es la causa de la mayoría de las búsquedas fallidas.

find responde preguntas sobre los atributos de un archivo o directorio: nombre, tipo, fecha de modificación, tamaño. Recorre el árbol de directorios y evalúa cada entrada, sin abrir nunca el archivo para ver qué hay escrito adentro.

grep —de global regular expression print, heredado de un comando del editor ed— hace lo opuesto: lee cada archivo línea por línea y lo compara contra un patrón de texto o una expresión regular (una secuencia que describe un conjunto de cadenas posibles, no una sola palabra). Su salida son líneas que coinciden, no rutas.

01
-exec {} \; frente a {} +

Uno ejecuta el comando por archivo; el otro agrupa varios en menos invocaciones y suele ser más eficiente.

02
-print0 y xargs -0

Sin este par, un nombre con espacios se corta en dos argumentos al pasar por una tubería.

03
BRE, ERE y PCRE

En las básicas hay que escapar +, ?, | y paréntesis; en las extendidas (-E) son directos; PCRE (-P) no es universal.

Para atributos, find; para contenido, grep; para las dos cosas a la vez, una tubería.

Diagrama de dos paneles y una tubería. El panel izquierdo, find, filtra rutas de archivo por metadatos: nombre con -name o -iname, tipo con -type, fecha de modificación con -mtime y tamaño con -size; su salida son rutas de archivo. El panel derecho, grep, filtra por contenido: un patrón de texto o expresión regular, con opciones -i para ignorar mayúsculas, -n para el número de línea y -E para expresiones regulares extendidas; su salida son líneas de texto que coinciden. Debajo, un tercer bloque muestra la tubería find punto -type f -name asterisco punto log -print0 seguido de xargs guion cero grep -l error, con -print0 y -0 remarcados en celeste: ese byte nulo evita que un nombre con espacios se corte en dos argumentos.
find filtra por metadatos y grep filtra por contenido; la tubería con -print0 y xargs -0 es la forma segura de unir ambos filtros.

Cómo buscar archivos con find

La sintaxis general de find es find [ruta...] [expresión]. Si no indicás una ruta, busca desde el directorio actual. La expresión combina pruebas (condiciones sobre cada entrada) y, si hace falta, acciones sobre lo que encuentra; sin una acción explícita, find simplemente imprime la ruta de cada coincidencia.

Bash
find . -name "*.log"
find /var/log -type f -name "*.log"
find . -type d -name "node_modules"
find /home/usuario -mtime -7
find . -size +100M
find /var/www -type f -name "*.php" -mtime -1

La primera busca archivos .log desde el directorio actual; la segunda limita el tipo y la ruta a /var/log, uno de los directorios que la estructura de directorios de Linux (FHS) reserva para registros del sistema; la tercera busca directorios node_modules; la cuarta lista lo modificado en la última semana; la quinta filtra por tamaño; la última combina tipo, nombre y fecha en una sola expresión.

Pruebas y opciones más usadas de find
Prueba u opciónQué evalúaEjemplo
-name / -inamePatrón sobre el nombre del archivo; -iname no distingue mayúsculasfind . -iname "*.pdf"
-type f, d, lTipo de entrada: archivo, directorio o enlace simbólicofind . -type d
-mtime -n / +nDías desde la última modificación, con signofind . -mtime -7
-sizeTamaño con sufijos c, k, M, Gfind . -size +100M
-maxdepth nLimita la profundidad del recorridofind . -maxdepth 1
-emptyArchivos o directorios vacíosfind . -type f -empty
-newer archivoMás reciente que un archivo de referenciafind /etc -newer /etc/hostname

Por defecto find une varias pruebas con un «y» lógico implícito: una entrada tiene que cumplirlas todas para aparecer en el resultado.

Acciones de find: -exec {} \; frente a {} + y -delete

Encontrar rutas no siempre alcanza: a veces hace falta hacer algo con cada una, y las dos formas de cerrar -exec se comportan de manera muy distinta.

-exec comando {} \; ejecuta el comando una vez por cada archivo; {} se reemplaza por la ruta, y el punto y coma se escapa con \ porque, sin escapar, la terminal lo tomaría como el fin de su propia instrucción. Con mil archivos, arranca mil procesos, uno detrás de otro.

-exec comando {} + agrupa tantos nombres como puede en cada invocación, como xargs: resuelve el mismo trabajo con uno o unos pocos procesos. Por eso conviene siempre que el comando acepte varios argumentoschmod, rm, grep—; {} \; solo tiene sentido si cada invocación necesita ser independiente.

Bash
# Una invocación por archivo: más procesos, más lento en árboles grandes
find . -name "*.tmp" -exec rm {} \;

# Una sola invocación agrupando varios archivos: más eficiente
find . -name "*.tmp" -exec rm {} +

# Dar permisos de ejecución a todos los scripts .sh de una vez
find . -type f -name "*.sh" -exec chmod +x {} +

find también trae -delete, más directa que -exec rm {} \; porque no depende de otro proceso. Antes de borrar de verdad:

  • Corré primero la misma expresión con -print y revisá la lista completa.
  • Restringí ruta y pruebas todo lo posible antes de una acción destructiva.
  • -delete no pide confirmación ni usa papelera: es irreversible.

El error más común: espacios, -print0 y xargs -0

Por defecto, find imprime una ruta por línea. El problema aparece al enviar ese resultado por una tubería a xargs —el comando que convierte líneas de entrada en argumentos de otro comando—, porque sin opciones separa los argumentos por espacios y saltos de línea. Un archivo llamado informe final.txt se parte en dos argumentos, informe y final.txt, y el comando siguiente recibe dos rutas inexistentes en vez de una.

Bash
# Se rompe si algún nombre tiene espacios
find . -name "*.txt" | xargs grep -l "REVISAR"

# Sobrevive a espacios, saltos de línea y comillas en el nombre
find . -name "*.txt" -print0 | xargs -0 grep -l "REVISAR"

La solución es el par -print0 y xargs -0. -print0 le dice a find que termine cada ruta con un byte nulo en lugar de un salto de línea; xargs -0 interpreta la entrada de esa misma manera. Como un byte nulo nunca forma parte de un nombre de archivo válido en Linux, sirve como separador inequívoco: no importa si el nombre tiene espacios, tabulaciones o comillas, llega entero al otro lado de la tubería. Es, con diferencia, el error más frecuente al combinar find con grep a través de xargs.

Cómo buscar texto con grep

Esta sección retoma un aporte de la comunidad: el hilo «A brief introduction to Linux | Part XI: Expresiones regulares y Metacaracteres», de TerminusRoot en el foro de Underc0de, ya explicaba con ejemplos reales buena parte de lo que sigue —-v, -n, -i, -E, las anclas ^ y $, el punto como comodín y el escapado con \—. Sigue vigente; esta guía lo reorganiza junto con la parte de find, sin hilo equivalente en el foro.

La sintaxis general es grep [opciones] patrón [archivo...]: lee cada archivo línea por línea y, por defecto, imprime las líneas donde aparece el patrón.

Bash
grep -n "error" /var/log/syslog
grep -i "error" /var/log/syslog
grep -v "^#" /etc/ssh/sshd_config
grep -rl "REVISAR" ./src
grep -r --include="*.py" "import os" .

La primera muestra coincidencias de «error» con número de línea; la segunda hace lo mismo sin distinguir mayúsculas; la tercera invierte la búsqueda y muestra lo que no empieza con #, útil para revisar la configuración activa de un archivo lleno de comentarios; la cuarta busca de forma recursiva y solo lista los archivos con coincidencias; la última limita esa búsqueda a archivos .py.

Opciones más usadas de grep
OpciónQué haceEjemplo
-r / -RBúsqueda recursiva dentro de directoriosgrep -r "REVISAR" ./src
-iIgnora mayúsculas y minúsculasgrep -i "error" registro.log
-nMuestra el número de línea de cada coincidenciagrep -n "error" registro.log
-lSolo lista los nombres de archivo con coincidenciasgrep -rl "REVISAR" ./src
-vInvierte la coincidencia: imprime lo que no matcheagrep -v "^#" archivo.conf
-EActiva expresiones regulares extendidas (ERE)grep -E "fail|error" registro.log
-FInterpreta el patrón como cadena fija, sin regexgrep -F "a+b" archivo.txt
--include=PATRÓNLimita la búsqueda recursiva a archivos que matcheen el patróngrep -r --include="*.py" "import os" .

BRE, ERE y PCRE: qué cambia de verdad

Una expresión regular es un patrón que describe un conjunto de cadenas posibles, no una sola palabra literal. POSIX define dos modos, y GNU grep agrega un tercero que ya no es POSIX.

Las expresiones regulares básicas (BRE) son el modo por defecto de grep. En este modo, metacaracteres como +, ?, |, ( y ) no tienen significado especial a menos que los escapes con una barra invertida: \+, \?, \|, \(, \). Las expresiones regulares extendidas (ERE, con -E) invierten la regla: esos símbolos tienen significado especial de forma directa, y escaparlos se lo quita.

Bash
# BRE (por defecto): la alternancia necesita escape
grep "fail\|error" registro.log

# ERE: la alternancia es directa
grep -E "fail|error" registro.log

# Anclas de comienzo y fin de línea, iguales en BRE y ERE
grep "^root:" /etc/passwd
grep "bash$" /etc/passwd

# BRE: el "?" opcional necesita escape
grep "colou\?r" texto.txt
# ERE: el "?" es directo
grep -E "colou?r" texto.txt

# PCRE, no garantizado en todas las implementaciones de grep
grep -P "\d{3}-\d{4}" contactos.txt

Las anclas ^ y $ y el punto . como comodín funcionan igual en los dos modos POSIX; lo que cambia es solo el tratamiento de los metacaracteres de agrupación y repetición.

Comparación entre expresiones regulares básicas, extendidas y PCRE
ModoCómo se activaMetacaracteres + ? ( )Disponibilidad
BRE (básicas)Modo por defecto de grepHay que escaparlos con \ para que sean especialesGarantizada por POSIX en cualquier grep
ERE (extendidas)grep -ETienen significado especial de forma directaGarantizada por POSIX en cualquier grep
PCREgrep -P (GNU grep)Igual que ERE, más construcciones no POSIX (\d, \w, lookahead)No garantizada en todas las implementaciones

Si un patrón con |, + o ? no hace lo que esperás, fijate si estás en BRE sin escapar el símbolo, o si olvidaste -E.

Combinar find y grep con una tubería

La guía de redirecciones y tuberías en la terminal cubre la mecánica general de conectar la salida de un comando con la entrada del siguiente. Acá importa por qué conviene unir find y grep: ninguno cubre solo una búsqueda que combine atributos y contenido.

Bash
# Archivos .log que contienen "OutOfMemory"
find . -name "*.log" -print0 | xargs -0 grep -l "OutOfMemory"

# Archivos de /etc modificados después de /etc/hostname, que mencionan PermitRootLogin
find /etc -type f -newer /etc/hostname -print0 | xargs -0 grep -l "PermitRootLogin"

# Scripts Python modificados en los últimos 30 días con una marca REVISAR pendiente
find . -type f -name "*.py" -mtime -30 -print0 | xargs -0 grep -n "REVISAR"

# Alternativa sin xargs: -exec ya pasa el nombre completo, no hace falta -print0
find . -name "*.conf" -exec grep -l "Listen" {} +

El último ejemplo importa: con -exec grep ... {} +, find pasa los nombres directamente al comando, así que el problema de los espacios ni aparece. Estos patrones son los que después vas a encapsular dentro de un script de Bash para repetirlos con variables en lugar de reescribirlos cada vez.

Errores frecuentes

  • Combinar find con xargs sin -print0/-0. Funciona con nombres simples y se rompe con el primer archivo que tiene un espacio.
  • Elegir {} \; por costumbre en árboles grandes. Si el comando acepta varios argumentos, {} + hace el mismo trabajo con menos procesos.
  • Usar | en grep básico sin -E ni escaparla. En BRE, | es literal hasta que lo escapás o activás -E.
  • Creer que grep -i y find -iname cubren lo mismo. Uno mira el contenido; el otro, el nombre del archivo.
  • Correr -delete o -exec rm sin probar antes con -print. Ninguna pide confirmación ni tiene deshacer.
  • Dejar el patrón sin comillas. La terminal puede expandir comodines antes de que grep o find los reciban.

Preguntas frecuentes

¿Cuál es la diferencia entre buscar por metadatos con find y buscar contenido con grep?

find recorre un árbol de directorios y evalúa los atributos de cada entrada —nombre, tipo, fecha de modificación, tamaño— sin mirar el contenido. grep hace lo opuesto: lee cada archivo línea por línea y compara el texto contra un patrón. Ninguno reemplaza al otro: find filtra por atributos, grep filtra por contenido, y se combinan con una tubería cuando la búsqueda necesita ambas cosas, por ejemplo archivos recientes que además contengan cierta palabra.

¿Cómo busco archivos por nombre, tipo, fecha o tamaño?

Con las pruebas de find: -name o -iname por nombre, -type f o -type d por si es archivo o directorio, -mtime -7 por fecha de modificación, y -size +100M por tamaño. Se combinan en una sola expresión: find /var/log -type f -name "*.log" -mtime -7 -size +10M filtra las cuatro cosas a la vez. Con -maxdepth n limitás cuántos niveles recorre antes de evaluar cada prueba.

¿Cuándo uso -exec {} \; y cuándo -exec {} + o -print0 con xargs -0?

-exec comando {} \; ejecuta el comando una vez por archivo: más lento en árboles grandes porque arranca un proceso por coincidencia, pero sirve si cada invocación debe ser independiente. -exec comando {} + agrupa varios nombres por invocación y lanza muchos menos procesos, ideal si el comando acepta varios argumentos, como chmod o rm. -print0 con xargs -0 resuelve otro problema: pasar nombres con espacios por una tubería sin que se corten en dos argumentos.

¿Qué hace cada opción común de grep?

-r o -R busca recursivo; -i ignora mayúsculas; -n muestra el número de línea; -l solo lista archivos con coincidencias; -v invierte el resultado; -E activa expresiones regulares extendidas; -F trata el patrón como cadena literal; y --include="*.py" limita la búsqueda recursiva a ese patrón de nombre. Se combinan: grep -rn --include="*.py" "import os" . busca recursivo, solo en .py, con número de línea.

¿Qué es una expresión regular básica frente a una extendida y a PCRE?

POSIX define dos modos. Las básicas (BRE), modo por defecto de grep, no dan significado especial a +, ?, | ni a los paréntesis salvo que los escapes con \. Las extendidas (ERE), con -E, les dan ese significado de forma directa. GNU grep suma un tercer modo con -P: expresiones compatibles con Perl (PCRE), con construcciones no POSIX como \d o el lookahead, no garantizadas en todas las implementaciones de grep.

¿Por qué combinar find y grep con una tubería en vez de usar solo uno de los dos?

Porque cada uno resuelve la mitad del problema: find no mira contenido y grep no filtra por metadatos. Cuando la búsqueda combina ambos criterios, find selecciona las rutas y grep revisa su contenido. La forma segura es find ... -print0 | xargs -0 grep ..., porque el byte nulo evita que un nombre con espacios se parta en dos argumentos, el error más común al combinarlos.

Fuentes

Aportes de la comunidad y documentación oficial consultados para esta guía. Fecha de consulta: 29 de julio de 2026.

Aportes de la comunidad Underc0de

  1. Underc0de, foro. A brief introduction to Linux | Part XI: Expresiones regulares y Metacaracteres, por TerminusRoot, sección GNU/Linux. Origen de la sección de grep y expresiones regulares de esta guía: cubre -v, -n, -i, -E, las anclas ^ y $, el punto como comodín y el escapado con barra invertida, y sigue vigente.

La parte de find de esta guía no se apoya en ningún hilo del foro: no existe un aporte previo de la comunidad sobre este comando, así que esa sección es contenido nuevo. La parte VI de la misma serie de TerminusRoot, «Operaciones de Archivos y Directorios», es una lectura relacionada sobre manejo de archivos en la terminal, pero no trata find.

Documentación oficial

  1. man7.org. find(1). Sintaxis completa de pruebas y acciones de find.
  2. man7.org. grep(1). Opciones de grep y comportamiento por defecto.
  3. man7.org. xargs(1). Comportamiento de -0 y el problema de separación por espacios.
  4. GNU. GNU grep Manual. Detalle de BRE, ERE y las extensiones PCRE de GNU grep.
  5. GNU. GNU Findutils Manual. Referencia extendida de find, incluida la diferencia entre -exec {} \; y -exec {} +.
  6. The Open Group. POSIX Base Specifications — grep. Definición estándar del comportamiento de grep.
  7. The Open Group. POSIX Base Specifications — find. Definición estándar de find.
  8. The Open Group. POSIX Base Specifications — Regular Expressions. Definición formal de BRE y ERE.