Un servidor en producción acumula decenas de miles de archivos. En srv-tramontana hay cuatro releases, copias de seguridad en tres carpetas, ficheros .bak- repartidos por donde alguien editó algo, y logs que crecen cada día. Cuando Marta pregunta «¿cuánto ocupan los releases viejos?» o cuando hay que averiguar si una credencial se ha colado en algún fichero, no sirve navegar con cd y ls: hay que preguntarle al sistema.

Esta lección te da las tres herramientas de búsqueda y, más importante, el criterio para elegir entre ellas. locate responde en milisegundos pero puede mentirte. find recorre el árbol de verdad y acepta criterios que ninguna otra herramienta ofrece. grep no busca archivos: busca dentro de ellos. Son tres problemas distintos, y confundirlos se paga en tiempo o en errores.

Contenido

  1. Tres herramientas, tres problemas
  2. locate: la base de datos precalculada
  3. find: anatomía de una búsqueda
  4. Criterios de find: nombre, tipo, tamaño, tiempo, propiedad, profundidad
  5. Combinar criterios con lógica
  6. Acciones: -print, -delete, -exec y -execdir
  7. Nombres con espacios y el patrón -print0 | xargs -0
  8. grep a fondo
  9. ripgrep, la alternativa moderna
  10. Casos reales de Tramontana

  1. Tres herramientas, tres problemas

Pregunta Herramienta Por qué
¿Dónde está el fichero que se llama X? locate Instantáneo; suficiente si el fichero no es reciente
¿Qué ficheros cumplen estas condiciones? find Único que filtra por tamaño, fecha, permisos, propietario
¿Qué ficheros contienen este texto? grep -r Es el único que abre y lee el contenido

La confusión típica es usar find para lo que hace grep o al revés. Regla mnemotécnica: find busca por las propiedades del archivo, grep busca por su contenido. Y se combinan constantemente, porque lo habitual es «busca en los ficheros que cumplen X si aparece Y».

  1. locate: la base de datos precalculada

locate no recorre el disco: consulta un índice generado periódicamente. En Ubuntu 24.04 la implementación es plocate.

operador@srv-tramontana:~$ sudo apt install -y plocate
operador@srv-tramontana:~$ locate confirmacion.html
/opt/tramontana/releases/3.2.1/plantillas/confirmacion.html
/opt/tramontana/releases/3.3.0/plantillas/confirmacion.html
operador@srv-tramontana:~$ touch /home/operador/datos/prueba-locate.txt
operador@srv-tramontana:~$ locate prueba-locate.txt      # sin salida: aún no indexado
operador@srv-tramontana:~$ sudo updatedb && locate prueba-locate.txt
/home/operador/datos/prueba-locate.txt

La base se actualiza una vez al día mediante una tarea programada. Hasta que se ejecute updatedb, lo que acabas de crear no existe para locate, y lo que acabas de borrar sigue apareciendo.

Opciones útiles: -i (ignora mayúsculas), -c (cuenta), -b '\nombre' (casa solo el nombre base), -l 5 (limita resultados), -e (verifica que el archivo aún existe). Cuándo usarlo: para localizar un fichero de sistema o de configuración cuyo nombre recuerdas a medias. Cuándo no: en cualquier procedimiento serio, y nunca como entrada de un comando destructivo. Un rm alimentado por locate puede intentar borrar rutas obsoletas o pasar por alto lo que sí debía borrarse.

  1. find: anatomía de una búsqueda

find <rutas> <criterios> <acciones>

Los tres bloques van en ese orden, y esa es la fuente de la mitad de los errores. find procesa los argumentos secuencialmente: todo lo que va antes del primer criterio lo interpreta como ruta.

operador@srv-tramontana:~$ find /opt/tramontana/releases -maxdepth 1 -type d
/opt/tramontana/releases
/opt/tramontana/releases/3.1.0
/opt/tramontana/releases/3.2.0
/opt/tramontana/releases/3.2.1
/opt/tramontana/releases/3.3.0

Si no indicas acción, find asume -print. Si no indicas ruta, usa el directorio actual; escribirla siempre es una buena costumbre, porque un find sin ruta lanzado desde / recorre el sistema entero.

  1. Criterios de find

Por nombre

Criterio Casa con
-name '*.log' el nombre base, distingue mayúsculas
-iname '*.LOG' igual pero sin distinguir
-path '*/plantillas/*' la ruta completa
-regex '.*/3\.[12]\..*' la ruta completa, con regex

El patrón va entre comillas simples, sin excepción: si no, Bash lo expande contra el directorio actual antes de que find lo vea, y buscas otra cosa.

Por tipo

-type f archivo regular, d directorio, l enlace simbólico, s socket, b/c dispositivos, p tubería con nombre.

find /opt/tramontana -maxdepth 1 -type l -ls te devuelve una sola entrada: el enlace de despliegue app -> releases/3.2.1 del Módulo 2, con su destino relativo.

Por tamaño

-size acepta sufijos: c bytes, k KiB, M MiB, G GiB. Sin sufijo, la unidad son bloques de 512 bytes, que casi nunca es lo que quieres. El signo delimita: +10M mayor que, -10M menor que, 10M exactamente (redondeado hacia arriba, así que rara vez es útil).

operador@srv-tramontana:~$ find /opt/tramontana -type f -size +10M -exec ls -lh {} +
-rwxr-x--- 1 root tramontana 48M ago 10 09:12 /opt/tramontana/releases/3.2.1/ejecutable
-rwxr-x--- 1 root tramontana 48M ago 15 11:03 /opt/tramontana/releases/3.3.0/ejecutable

Por tiempo

Aquí está el detalle que hay que entender bien porque genera resultados equivocados en silencio.

Criterio Unidad Significado
-mtime n días contenido modificado
-mmin n minutos contenido modificado
-atime / -amin días / minutos último acceso
-ctime / -cmin días / minutos metadatos cambiados
-newer FICHERO — más reciente que ese fichero

Por qué -mtime +7 no significa «modificado en los últimos 7 días» ni «hace más de 7 días» tal como lo dirías en voz alta. find calcula los días transcurridos y descarta la parte decimal. Un archivo de 7 días y 20 horas tiene una antigüedad de 7,83 días, que truncado es 7. Y +7 significa «estrictamente mayor que 7», así que ese archivo no casa. En la práctica, -mtime +7 selecciona lo que tiene más de 8 días de antigüedad.

Expresión Selecciona archivos con antigüedad
-mtime 0 menos de 24 h
-mtime -7 menos de 7 días
-mtime 7 entre 7 y 8 días exactamente
-mtime +7 8 días o más

Cuando la precisión importa —y en una purga automática importa— usa -mmin o, mejor, compara contra un fichero de referencia:

operador@srv-tramontana:~$ touch -d '2026-08-01 00:00' /tmp/ref
operador@srv-tramontana:~$ find /srv/tramontana/backups -type f ! -newer /tmp/ref

Eso es «anterior al 1 de agosto», sin ambigüedad y sin aritmética mental. Es la forma que usamos en Tramontana.

Por propiedad y permisos

operador@srv-tramontana:~$ find /var/log/tramontana -type f ! -group adm
operador@srv-tramontana:~$ find /opt/tramontana -type f -perm /u+s

El primero verifica que todos los logs tienen adm como grupo propietario; sin salida significa que la convención se cumple. El segundo es una auditoría de seguridad: busca binarios con SUID, ese bit que en 02-07 aprendiste a reconocer. La sintaxis de -perm tiene tres formas:

Forma Significa
-perm 640 permisos exactamente 640
-perm -640 al menos esos bits (puede tener más)
-perm /640 alguno de esos bits

También -user operador, -group tramontana, -uid 997, -nouser y -nogroup (huérfanos, típicos tras borrar una cuenta).

Por profundidad

operador@srv-tramontana:~$ find /opt/tramontana -maxdepth 2 -type d

-maxdepth y -mindepth son opciones de posición: deben ir antes que cualquier criterio. Si escribes find /opt -name '*.log' -maxdepth 2, find funciona pero avisa de que el resultado no es el que esperas, porque para entonces ya ha decidido descender. Ponlas siempre justo después de la ruta.

  1. Combinar criterios con lógica

Criterios consecutivos se combinan con Y implícito. Para el resto:

Operador Significado
-a Y (implícito, casi nunca se escribe)
-o O
! o -not negación
\\( \\) agrupación (los paréntesis van escapados)
operador@srv-tramontana:~$ find /home/operador -type f \( -name '*.bak-*' -o -name '*.tmp' \) -mtime +30
/home/operador/.bashrc.bak-2026-07-02
/home/operador/datos/reservas.csv.bak-2026-07-11

Los paréntesis son imprescindibles: sin ellos, la precedencia hace que -mtime +30 se aplique solo a la última alternativa, y te llevarías por delante todos los .bak-* sin importar su edad. Cuando mezcles -o con cualquier otra cosa, agrupa. Los paréntesis se escapan porque para Bash son metacaracteres; también valen '(' y ')'.

  1. Acciones

Acción Qué hace
-print imprime la ruta (por defecto)
-print0 igual, separando con byte nulo
-ls como ls -dils
-delete borra (evalúa antes que otros criterios: cuidado)
-exec CMD {} \; ejecuta CMD una vez por archivo
-exec CMD {} + ejecuta CMD agrupando archivos
-execdir CMD {} \; igual, pero desde el directorio del archivo
-ok CMD {} \; como -exec, pidiendo confirmación

{} es el marcador que find sustituye por la ruta. El terminador \; va escapado para que Bash no se lo quede.

\; frente a +: la diferencia de rendimiento

Con \; se lanza un proceso por archivo. Con +, find acumula rutas y lanza el mínimo número de procesos posible. Sobre 5.000 ficheros del sistema:

operador@srv-tramontana:~$ time find /usr/share/doc -type f -exec basename {} \; > /dev/null
real    0m11,482s
operador@srv-tramontana:~$ time find /usr/share/doc -type f -exec basename {} + > /dev/null
real    0m0,213s

Cincuenta veces más rápido. La diferencia no es el comando: es el coste de crear miles de procesos. Usa + siempre que el comando acepte varios argumentos. Necesitas \; solo cuando el comando admite un único argumento o cuando {} aparece en medio de la orden (por ejemplo -exec mv {} {}.old \;).

-execdir y por qué es más seguro

-execdir ejecuta el comando desde el directorio que contiene el archivo, y le pasa ./nombre en lugar de la ruta completa. Eso elimina una clase entera de problemas: rutas que empiezan por guion y que el comando interpretaría como opciones, y la condición de carrera en la que alguien sustituye un directorio intermedio por un enlace simbólico entre el momento en que find lo encuentra y el momento en que el comando actúa. Si vas a ejecutar algo destructivo sobre directorios donde escriben otros usuarios, -execdir es la opción correcta.

-delete, con cabeza

operador@srv-tramontana:~$ find /srv/tramontana/backups/temporales -type f -name '*.tmp' -mtime +7
/srv/tramontana/backups/temporales/export-1.tmp
/srv/tramontana/backups/temporales/export-2.tmp
operador@srv-tramontana:~$ find /srv/tramontana/backups/temporales -type f -name '*.tmp' -mtime +7 -delete

Siempre en dos pasos: primero sin -delete para ver la lista, después con él. Es la misma convención que ya aplicas al rm. Y una advertencia real: -delete implica -depth, y si lo colocas antes de los criterios, find lo evalúa antes y borra todo lo que encuentre. El orden importa.

  1. Nombres con espacios y el patrón -print0 | xargs -0

Los nombres de archivo en Linux pueden contener espacios, tabuladores y hasta saltos de línea. Cualquier tubería que separe rutas por espacios se rompe con ellos.

operador@srv-tramontana:~$ touch '/tmp/informe agosto.txt'
operador@srv-tramontana:~$ find /tmp -name '*.txt' | xargs ls -l
ls: no se puede acceder a '/tmp/informe': No existe el archivo
ls: no se puede acceder a 'agosto.txt': No existe el archivo

La solución es un separador que no puede aparecer en un nombre: el byte nulo. find lo emite con -print0 y xargs lo espera con -0.

operador@srv-tramontana:~$ find /tmp -name '*.txt' -print0 | xargs -0 ls -l
-rw-r----- 1 operador operador 0 ago 18 11:20 '/tmp/informe agosto.txt'

find ... -print0 | xargs -0 comando es el patrón canónico. Memorízalo tal cual.

xargs en sí

xargs construye líneas de comando a partir de su entrada estándar. Opciones que importan:

Opción Efecto
-0 entrada separada por bytes nulos
-n 5 como máximo 5 argumentos por invocación
-I{} sustituye {} por cada línea; implica un argumento por invocación
-P 4 ejecuta hasta 4 procesos en paralelo
-r, --no-run-if-empty no ejecutar nada si la entrada está vacía
-t muestra el comando antes de ejecutarlo (depuración)

--no-run-if-empty evita un error clásico: sin ella, xargs rm con entrada vacía ejecuta rm sin argumentos. En GNU es el comportamiento por defecto, pero escribirla explícita hace el comando portable y documenta la intención.

  1. grep a fondo

Opción Efecto
-i ignora mayúsculas
-v invierte: líneas que no casan
-n número de línea
-c solo cuenta coincidencias
-l / -L solo nombres de ficheros con / sin coincidencia
-r / -R recursivo (-R sigue enlaces simbólicos)
-w / -x palabra completa / línea completa
-o imprime solo la parte que casa
-A n / -B n / -C n n líneas después / antes / de contexto
-e P1 -e P2 varios patrones
-f fichero patrones leídos de un fichero
-E / -F / -P ERE / cadenas fijas / PCRE
--include / --exclude filtra qué ficheros se leen en modo recursivo
-q silencioso; solo importa $?
operador@srv-tramontana:~$ grep -n -A2 'ERROR 500' /var/log/tramontana/errores.log | head -6
41:2026-08-18 03:12:44 ERROR 500 /reservas db_timeout
42-2026-08-18 03:12:44 TRACE conexiones_activas=200
43-2026-08-18 03:12:45 WARN pool agotado
--
58:2026-08-18 03:19:02 ERROR 500 /reservas db_timeout

El contexto convierte una línea suelta en una historia: el error 500 va acompañado de conexiones_activas=200, que es exactamente el max_conexiones de app.conf. Ahí hay una hipótesis de diagnóstico.

-F frente a -E. Con -F, grep trata el patrón como texto literal y usa un algoritmo de búsqueda multipatrón mucho más rápido que un motor de expresiones regulares. Si buscas una cadena fija, -F es la opción correcta: más rápida y sin sorpresas con los metacaracteres. Buscar 10.0.2.15 con -E casaría también 10x0y2z15; con -F, solo la IP.

operador@srv-tramontana:~$ grep -rFl '10.0.2.15' /etc/tramontana/
/etc/tramontana/app.conf

-q como test. No imprime nada; solo devuelve 0 si encontró algo. Es la forma correcta de preguntar «¿aparece esto?» y encadenar con &&:

operador@srv-tramontana:~$ grep -q 'log_nivel=debug' /etc/tramontana/app.conf \
    && echo 'AVISO: la app está en modo depuración'
AVISO: la app está en modo depuración

Un hallazgo real: dejar log_nivel=debug en producción hincha los logs y puede volcar datos sensibles al fichero.

  1. ripgrep, la alternativa moderna

rg hace lo mismo que grep -r y es varias veces más rápido: recorre en paralelo, respeta .gitignore, ignora binarios y numera las líneas por defecto.

operador@srv-tramontana:~$ rg -n 'db_timeout' /var/log/tramontana/
errores.log:41:2026-08-18 03:12:44 ERROR 500 /reservas db_timeout
errores.log:58:2026-08-18 03:19:02 ERROR 500 /reservas db_timeout

Se instala con sudo apt install -y ripgrep. Es excelente para tu trabajo diario. Con una salvedad profesional: grep está en todas las máquinas y rg no. En un servidor ajeno, en un contenedor mínimo o en un procedimiento documentado, escribe grep.

  1. Casos reales de Tramontana

a) Releases antiguos para purgar. Cuánto ocupan y cuáles no son el activo:

operador@srv-tramontana:~$ readlink /opt/tramontana/app
releases/3.2.1
operador@srv-tramontana:~$ find /opt/tramontana/releases -maxdepth 1 -mindepth 1 -type d \
    ! -name '3.2.1' -exec du -sh {} +
97M     /opt/tramontana/releases/3.1.0
98M     /opt/tramontana/releases/3.2.0
99M     /opt/tramontana/releases/3.3.0

-mindepth 1 excluye el propio /opt/tramontana/releases, que si no aparecería en la lista. Antes de borrar nada: 3.3.0 es el siguiente release, no uno antiguo. La regla que fijamos es conservar el activo y el inmediatamente anterior, así que el candidato a purga es 3.1.0, y solo él. Este es el criterio que automatizaremos en 03-07.

b) Todos los .bak-* dispersos.

operador@srv-tramontana:~$ sudo find /etc /home /srv /opt -name '*.bak-*' -type f -printf '%TY-%Tm-%Td %10s %p\n' | sort
2026-07-02 3771 /home/operador/.bashrc.bak-2026-07-02
2026-07-11 1284 /home/operador/datos/reservas.csv.bak-2026-07-11
2026-08-18 512 /etc/tramontana/app.conf.bak-2026-08-18

-printf permite componer la salida exacta que quieres: %TY-%Tm-%Td la fecha de modificación, %10s el tamaño alineado, %p la ruta. Es más limpio que encadenar ls y awk.

c) Buscar una credencial por el sistema. Marta pregunta si la contraseña de la base de datos puede estar en algún sitio donde no debería:

operador@srv-tramontana:~$ sudo grep -rIl --exclude-dir='.git' -e 'db_password' /etc /home /srv /opt
/etc/tramontana/app.conf
/srv/tramontana/backups/temporales/app.conf.copia

Aparece donde debe... y donde no. -I omite los binarios (sin ella, el ejecutable de 48 MB se analiza inútilmente y puede ensuciar el terminal), -l da solo el nombre del fichero, y --exclude-dir evita ruido. La segunda ruta es un descubrimiento serio:

operador@srv-tramontana:~$ ls -l /srv/tramontana/backups/temporales/app.conf.copia
-rw-r--r-- 1 operador operador 512 ago 12 17:40 /srv/tramontana/backups/temporales/app.conf.copia

Permisos 644: legible por cualquier usuario del sistema, cuando el original es 640 de root:tramontana. Es una copia que Luis dejó al depurar un problema de conexión. Se elimina, y en el informe a Marta se dice qué protege la medida (nadie más puede leer esa credencial desde el servidor) y qué no (la contraseña estuvo expuesta seis días; hay que rotarla, porque borrar la copia no deshace la exposición). Esa distinción es la que se espera de ti.

d) Contar errores por tipo.

operador@srv-tramontana:~$ grep -c '' /var/log/tramontana/errores.log
87
operador@srv-tramontana:~$ grep -oE 'ERROR [0-9]{3}' /var/log/tramontana/errores.log | sort | uniq -c | sort -rn
     41 ERROR 500
     28 ERROR 503
     18 ERROR 404

grep -c '' cuenta todas las líneas —el patrón vacío casa siempre—: 87, como esperábamos. De ellas, 41 son errores 500 de servidor. Eso ya es un informe.

Errores Comunes y Consejos

  • No entrecomillar el patrón de -name. Bash lo expande contra el directorio actual y find recibe otra cosa.
  • Poner -maxdepth después de los criterios. Debe ir inmediatamente tras la ruta.
  • Mezclar -o sin paréntesis. La precedencia hará que el último criterio se aplique solo a una rama.
  • Interpretar -mtime +7 literalmente. Son 8 días o más. Si importa, usa ! -newer fichero-de-referencia.
  • Encadenar find | xargs sin -print0/-0. Se rompe con el primer nombre que lleve un espacio.
  • Usar -exec ... \; sobre miles de ficheros. Cambia a + y ganas un orden de magnitud.
  • Poner -delete antes de los criterios. Se evalúa primero y borra de más. Y no te fíes de locate para tomar decisiones: es una foto de ayer, verifica con find o con ls.
  • Consejo: find mezcla en la salida los avisos de directorios sin permiso. Añade 2>/dev/null para silenciarlos —lo verás en detalle en 03-04— pero solo cuando sepas que no te interesan. Y ante un find complejo, ejecútalo primero con -ls: es su --dry-run.

Ejercicios

Ejercicio 1. Localiza en /home/operador todos los archivos regulares mayores de 1 MiB modificados hace más de dos semanas, mostrando fecha, tamaño y ruta ordenados por fecha. Explica por qué no has usado -mtime +14 a secas.

Ejercicio 2. Averigua qué ficheros de configuración del sistema mencionan el puerto de la base de datos de Tramontana (5432), excluyendo binarios y sin que los nombres con espacios rompan nada. Después cuenta cuántas veces aparece en total.

Ejercicio 3. Prepara —sin ejecutarla— la purga del release 3.1.0 y de todos los ficheros .tmp de más de 7 días en /srv/tramontana/backups/temporales. Muestra exactamente qué se borraría, cuánto espacio se liberaría, y justifica la verificación previa que harías para no borrar el release activo.

Soluciones

Solución 1.

operador@srv-tramontana:~$ touch -d '2026-08-04 00:00' /tmp/ref-14d
operador@srv-tramontana:~$ find /home/operador -type f -size +1M ! -newer /tmp/ref-14d \
    -printf '%TY-%Tm-%Td %8s %p\n' | sort
2026-07-11 2097152 /home/operador/datos/export-junio.tar.gz
2026-07-29 5242880 /home/operador/trabajo/2026/07/datos/volcado.sql

Se evita -mtime +14 porque su semántica real es «15 días o más», por el truncamiento de la parte decimal que vimos en el apartado 4. Con un fichero de referencia creado con touch -d la frontera es una fecha concreta y verificable, no el resultado de una aritmética que hay que recordar. En una purga automática esa diferencia de un día puede significar borrar la única copia que quedaba. -printf y sort sustituyen a ls -l, que no admite ordenar por fecha una lista arbitraria de rutas.

Solución 2.

operador@srv-tramontana:~$ sudo grep -rIlF --exclude-dir=.git '5432' /etc 2>/dev/null
/etc/tramontana/app.conf
/etc/postgresql/16/main/postgresql.conf
operador@srv-tramontana:~$ sudo grep -rIhoF '5432' /etc 2>/dev/null | wc -l
7

-r maneja el recorrido internamente, así que no hay tubería que romper: el problema de los nombres con espacios ni se plantea. Es la primera lección de la solución: si grep -r te basta, no montes find | xargs. -I descarta binarios, -F trata 5432 como literal (es un número, no hay metacaracteres, pero es más rápido y explícito), y 2>/dev/null silencia los avisos de permiso denegado en subdirectorios de /etc que ni siquiera con sudo interesan. Para contar, -h suprime el nombre del fichero y -o emite una línea por coincidencia, de modo que wc -l cuenta apariciones y no líneas que contienen alguna.

Solución 3. Primero la verificación que no se puede saltar:

operador@srv-tramontana:~$ readlink /opt/tramontana/app
releases/3.2.1

El activo es 3.2.1, luego 3.1.0 no es el activo. Esta comprobación va siempre antes, porque el enlace app es la única fuente de verdad sobre qué release está sirviendo: fiarse de la memoria o del número más alto es como se borra un release en producción. Y hay que hacerla ahora, no ayer.

operador@srv-tramontana:~$ du -sh /opt/tramontana/releases/3.1.0
97M     /opt/tramontana/releases/3.1.0
operador@srv-tramontana:~$ find /srv/tramontana/backups/temporales -type f -name '*.tmp' -mtime +7 \
    -printf '%TY-%Tm-%Td %8s %p\n'
2026-08-02  4096 /srv/tramontana/backups/temporales/export-1.tmp
2026-08-05  8192 /srv/tramontana/backups/temporales/export-2.tmp

Total a liberar: 97 MiB más 12 KiB. Los comandos que ejecutaríamos, ya validados por las listas anteriores:

# sudo rm -rf /opt/tramontana/releases/3.1.0
# find /srv/tramontana/backups/temporales -type f -name '*.tmp' -mtime +7 -delete

Están comentados a propósito: el ejercicio pedía prepararlos. Nótese que el segundo comando es literalmente el mismo que el de la verificación con -delete añadido al final. Ese es el procedimiento correcto: no se escribe un comando nuevo para borrar, se le añade la acción al comando que ya has visto funcionar. Cualquier cambio en el patrón entre la comprobación y el borrado invalida la comprobación.

Conclusión

Ya no navegas un servidor: lo interrogas.

  • Eliges entre las tres: locate para «dónde está», find para filtrar por propiedades del archivo, grep para buscar contenido. Y conoces el defecto de locate: es una foto de ayer hasta el siguiente updatedb.
  • Dominas find <rutas> <criterios> <acciones> y los criterios por nombre, tipo, tamaño, tiempo, propietario, permisos y profundidad, con las tres formas de -perm y las posicionales colocadas donde deben ir.
  • Entiendes de verdad -mtime +7 y sabes que la alternativa robusta es ! -newer sobre un fichero de referencia.
  • Combinas criterios con -o, ! y paréntesis escapados, sabiendo por qué la agrupación no es opcional.
  • Usas -exec ... + en lugar de \; porque la diferencia es de un orden de magnitud; conoces -execdir, y aplicas -delete solo después de haber visto la lista.
  • Tienes interiorizado el patrón canónico find ... -print0 | xargs -0 y manejas xargs con -n, -I{}, -P y --no-run-if-empty.
  • Manejas grep con contexto, recursividad, -o, -F para literales y -q como test encadenable, y conoces rg como alternativa rápida que no siempre estará instalada.
  • Y has resuelto cuatro problemas reales: cuantificar los releases purgables sin tocar el activo, inventariar los .bak-*, encontrar una credencial expuesta en una copia olvidada —con la conclusión honesta de que borrarla no basta y hay que rotar la contraseña— y contar los errores de errores.log por tipo.

En varios de esos comandos has usado 2>/dev/null, | y > sin que nadie te haya explicado del todo qué son. Eso se acaba en la siguiente lección. Tuberías y Redirección desmonta la mecánica: los tres flujos estándar y por qué existen, cómo verlos en /proc, qué es realmente una tubería, la diferencia entre &>fichero, >fichero 2>&1 y el clásico error 2>&1 >fichero que casi todo el mundo comete, y el patrón | sudo tee para escribir en ficheros protegidos. Al terminarla habrás dejado de encadenar comandos por imitación y empezarás a componerlos sabiendo exactamente por dónde circula cada byte.

Curso de Linux: De Principiante a Administrador de Sistemas

Módulo 1: Introducción a Linux

Módulo 2: Comandos Básicos de Linux

Módulo 3: Habilidades Avanzadas en la Línea de Comandos

Módulo 4: Scripting en Shell

Módulo 5: Administración del Sistema

Módulo 6: Redes y Seguridad

Módulo 7: Temas Avanzados

Módulo 8: Proyectos Prácticos

© Copyright 2026. Todos los derechos reservados