Dos de los comandos más poderosos que podemos encontrar en una terminal son find y grep, que nos permiten realizar búsquedas dentro de grandes sistemas de ficheros de manera rápida y eficiente.
La mejor forma de comprender el poder de estas herramientas es ponerlas en contexto.
El primer ejemplo es una situación bastante común, en el trabajo alguien renuncia y realiza una entrega o transferencia de conocimiento, sin embargo, tiempo después, cuando alguien revisa algún trabajo o proyecto que eran responsabilidad de esta persona, se dan cuenta que no esta la información completa, o no encuentran el archivo clave que se necesita.
La primera opción es realizar una búsqueda manual sobre el sistema de archivos, peros si la persona no es era muy organizada, y llevaba mucho tiempo almacenando información en el equipo, la tarea puede ser titánica, sin embargo tu sales al rescate, con tus conocimientos de la línea de comandos.
La primera aproximación para encontrar la información es buscar una carpeta o archivo de la cual saben el nombre, para esto usamos find con la siguiente estructura:
find /directorio -opciones
En un ejemplo podríamos tener lo siguiente:
find ./ -name nombre_de_archivo.docx -type f
Lo que nos buscaría el archivo (-type f) con nombre nombre_de_archivo.docx (-name). Podemos transformar la búsqueda en ignore case cambiando -name por -iname.
Otro ejemplo es la búsqueda de todos los archivos de con cierta extensión, lo que se vería similar a lo siguiente:
find ./ -type f -iname *.pdf
Esto nos buscará todos los archivos con extensión pdf dentro del directorio actual y todos los subdirectorios. El uso del comodín * nos permite decirle que buscamos archivos con cualquier nombre, pero con la extensión .pdf.
Dentro de las opciones más comunes en tipo de archivo tenemos:
Además de las opciones anteriores, se pueden realizar búsquedas por parámetros como tiempo o peso de los archivos, recuerda revisar las opciones completas con el comando man find.
No conseguimos encontrar lo que buscamos por nombre, pero sabemos que contienen un conjunto de palabras clave que nos permitirían descartar otro tipo de archivos y reducir la búsqueda, para este tipo de situaciones tenemos a grep.
El comando grep busca una expresión dentro del contenido de uno o varios archivos, la forma básica se ve como sigue:
grep -opciones patron archivo_o_directorio
Una búsqueda básica es encontrar cierta línea en un archivo estructurado, por ejemplo un directorio de usuarios, si conocemos algún dato del usuario que buscamos, podemos realizar lo siguiente:
grep -i"Nombre Usuario" directorio.csv
Nos encontrará todas las líneas con el nombre “Nombre Usuario”, sin importar si se utilizan mayúsculas o minúsculas, por el modificador -i.
Si ahora suponemos que se busca un oficio con un identificador único, podemos realizar la siguiente búsqueda:
grep -ri Oficio-1423-534 ./
Nos realizará una búsqueda recursiva, activada por el modificador -r, de la expresión “Oficio-1423-634” en el directorio actual, y todos sus subdirectorios
Cada uno de los comandos son poderosos por ellos mismos, sin embargo cuando los utilizamos juntos podemos realizar operaciones muy complejas con poco esfuerzo.
Para ver el poder de estos amigos, permitan que les plantee la siguiente situación:
En un servicio de hosting web con cPanel, se generan varias cuentas de correo electrónico, dentro de estas cuentas el correo se almacenan en directorios con el nombre de usuario, donde cada correo se almacena en un archivo.
Recientemente se ha presentado la una situación en la que llega correo no deseado con un ritmo de entre 5 a 15 correos por minuto, y la herramienta de spam no es capas de hacerle frente.
El primer acercamiento es analizar el contenido de los correos no deseados, y encontrar los elementos que lo identifican, como una dirección de remitente, el emisor, etc. Con esto en la mano podemos apoyarnos con grep para encontrar todos los archivos con ese elemento identificador:
grep -ri identificador /carpeta/usuarios/correo
Pero al ejecutar la búsqueda nos percatamos que tarda mucho, esto seguramente resultado del gran volumen de archivos almacenados en los subdirectorios. ¿Qué podemos hacer ante esta situación?
Para reducir el universo de documentos donde grep deberá buscar el identificador, utilizaremos find para encontrar aquellos elementos susceptibles de ser problemáticos, pero ¿Cómo los podemos identificar?; fácil, la situación comenzó hace poco, por lo que solo deberemos buscar en los archivos que tengan menos de cierto tiempo.
find -type f -mtime -1
Este comando nos lista todos los archivos que tienen un tiempo de modificación menor a 1 día (-1), y para pasar esa información a grep, usaremos una tubería.
find -typef -mtime -1 | xargs grep -il identificador
Esto nos regresará las ubicaciones de aquellos archivos con fecha de modificación menor a 1 día, que dentro de su contenido contienen el “identificador” que nos interesa. De los elementos nuevos en esta búsqueda tenemos xargs, que genera la ejecución del comando que le sigue, pasándole como argumento cada una de las líneas generadas en el comando anterior (antes de la tubería); el modificador l para grep, le indica que solo muestre el nombre del documento donde hay coincidencia
Con esto casi terminamos, pero ahora, ¿Qué haremos con este resultado?
Tenemos varias opciones, podemos moverlo, eliminarlo, registrarlo, etc. Como ejemplo nosotros lo eliminaremos con las instrucciones siguientes:
find -typef -mtime -1 | xargs grep -il identificador | xargs rm
Utilizamos nuevamente una tubería y el comando xargs, para que aquellos elementos con el identificador especificado, se borren con la instrucción rm.
Como podemos ver, es uso de estos comandos en conjunto nos permiten realizar grandes cosas con pocas líneas, siempre y cuando sepamos que es lo que buscamos, podemos filtrar una gran cantidad de archivos sin apenas esfuerzo.
¿Qué sigue después de esto?
Automatizar tareas, la búsqueda que construimos ya realiza una tarea, pero si tenemos que realizarla manualmente cada cierto tiempo (en lo que se resuelve el problema del ingreso del correo no deseado por ejemplo), vamos a esclavizarnos innecesariamente, podemos automatizar estas tareas con un simple script de bash, y utilizando cron para repetir la tarea cada cierto tiempo.