Revista Tecnología

Píldora: Cómo buscar un texto dentro de documentos múltiples ODT de Libreoffice/Openoffice o docx de Microsoft Word

Publicado el 30 abril 2018 por Gaspar Fernández Moreno @gaspar_fm

Píldora: Cómo buscar texto dentro documentos múltiples Libreoffice/Openoffice docx Microsoft WordPíldora: Cómo buscar un texto dentro de documentos múltiples ODT de Libreoffice/Openoffice o docx de Microsoft WordCuántas veces has recordado haber escrito un documento y no recuerdas dónde lo pusiste. Tienes cientos de archivos de documentos en tu disco duro, o en un servidor y no sabes por dónde empezar a buscar. Con ficheros de texto, podemos utilizar find, grep, egrep, sed y algunos comandos más que, combinados podrán darnos los resultados que buscamos. Aunque los archivos de documentos son algo más complejos internamente.

Ficheros de documentos

Tanto los ficheros de OpenOffice/LibreOffice como los documentos de Microsoft Word Open XML (esos archivos docx que se crean a partir de Microsoft Office 2007. En este post no podremos buscar documentos generados con versiones más antiguas del programa) son en realidad archivos ZIP con muchos archivos XML en su interior en los que se definen contenido, estilos y metadatos. Para los archivos odt, de LibreOffice y OpenOffice, el archivos que contiene los contenidos del documento es content.xml y en Microsoft Word, el archivo está situado en word/document.xml, así que, vamos a intentar, buscar todos los archivos de documentos que haya en una ruta del disco y examinar su contenido para buscar las palabras que necesitamos encontrar. Para ello tendremos que descomprimir el documento y extraer el archivo del documento. Todo de forma automática.

Es cierto que actualmente tenemos programas de búsqueda en escritorio, que examinan periódicamente archivos en varios formatos, procesan dicha información y agilizan la muestra de resultados. Aunque en muchos casos, para acelerar el uso normal del ordenador, muchos los solemos tener desactivados. O, por ejemplo, si tienes los contenidos en un ordenador remoto, una Raspberry PI, o un VPS, puede resultar un poco más complicado hacer dichas búsquedas.

Afortunadamente GNU/Linux nos proporciona herramientas muy buenas para realizar nuestras tareas. Primero ejecutaremos find para obtener todos los archivos de documento a partir de la ruta actual. Aunque podríamos utilizar find con otros parámetros o incluso utilizar locate. Para ello, podemos utilizar estos scripts de una línea, también llamados one-liners.

Documentos de LibreOffice/OpenOffice

Empezaremos con los documentos odt de LibreOffice u OpenOffice. Para ello extraeremos el archivo word/document.xml del archivo de documento y a partir de ahí realizaremos una búsqueda.

De esta forma, find, va pasando archivos odt al resto de la línea. Podríamos hacer fácilmente que no sean todos los archivos, si nos acordamos de parte del nombre podríamos hacer '*informe*.odt' para seleccionar todos los docuentos que contentan la palabra informe y tengan extensión odt; o incluso utilizar -iname en lugar de -name para indicar que busque nombres de archivo en mayúsculas y minúsculas indistintamente. También, con find podríamos seleccionar incluso los archivos por tamaño o por fecha.

En lugar de find -name '*.odt' podríamos utilizar locate '*.odt' para buscar en todo el disco, o en un patrón de directorios determinado. La ventaja de locate es su gran velocidad, aunque primero tendremos que crear una base de datos de archivos del disco (con updatedb) y eso puede tardar un poco.

Una vez tenemos los nombres de archivo que cumplen el patrón, cogemos cada nombre de archivo y ejecutamos unzip -p [archivo] content.xml. La opción -p sirve para extraer el contenido de los archivos directamente a la salida estándar de la aplicación. Si ejecutamos este comando individualmente, veríamos todos los contenidos del fichero en pantalla, vamos, extrae todo a pantalla, en lugar de crear un archivo llamado content.xml. La ventaja de esto es que no necesitamos archivos temporales y todo es mucho más rápido.

La salida de unzip, es decir, el contenido del fichero comprimido, se lo pasamos a grep. En este caso, grep -li "TEXTO" > /dev/null. Con -l, hacemos que grep muestre solo los nombres de archivo donde exista coincidencia, así sólo es necesario que el texto se encuentre una vez en el archivo para que grep finalice la ejecución y devuelva un positivo. Lo malo es que si el texto no está en el archivo tendrá que analizarlo completamente. El argumento -i hace que no importen las mayúsculas y minúsculas, por lo que, aunque en el documento encontremos "CaCaHueTe", podremos decir que grep busque "cacahuete" y lo va a encontrar sin problema. Por último, la salida de grep la redirigimos a /dev/null para que realmente no muestre nada en pantalla. ¿Por qué?

Lo que en realidad analizaremos de grep será el estado de salida del programa. Es decir, internamente, si grep acaba y el archivo que ha analizado contiene el texto que buscamos, devolverá un 0 (normalmente, cuando un programa finaliza bien devuelve un 0 y cuando no, devuelve otra cosa). Entonces, sólo si grep devuelve 0 mostraremos el nombre del archivo en pantalla. Para eso if [ $? -eq 0 ]; then echo $file; fi;.

Documentos de Microsoft Word

Para hacer lo mismo con los documentos de Microsoft Word debemos cambiar el archivo que analizamos. En este caso, analizaremos word/document.xml. Y mantendremos todo el comando igual:

Mejorar la búsqueda

Los ficheros que estamos analizando, en realidad son XML, por lo que, junto con el contenido encontramos algunos datos que nos indicarán estilos, objetos empotrados, notas, y demás cosas. Todo esto puede hacer que cuando busquemos algún contenido concreto no lo encontremos. Para mejorar la búsqueda, aunque penalizaremos un poco el tiempo que tardará el script, sobre todo en archivos muy grandes. La clave está en eliminar las etiquetas XML que encontramos en el archivo de contenidos. Un claro ejemplo, podemos verlo si analizamos un fichero HTML. Cuando vemos:

En realidad, el código utilizado para el texto es este:

Y si realizamos una búsqueda en texto con grep, por ejemplo, buscando la palabra "Hola". Grep no encontrará nada. Así que, pasaremos el texto por un filtro que eliminará estas etiquetas, con sed. Uno de los usos de este comando es reemplazar cadenas a través de expresiones regulares, pero aunque suene complicado, os la voy a dar preparada. Para ver un ejemplo rápido, vamos a hacer lo siguiente:

echo "Hola Mundo" | grep -i hola


Esto no devolverá nada, porque, como hemos dicho antes, no vamos a encontrar nada en la cadena anterior. Pero,


El segundo ejemplo sí que devuelve el contenido. El objetivo es sustituir globalmente (s/búsqueda/reemplazo/g) cualquier texto que esté entre < y > (<[^>]*< por un texto en blanco.

Creando el script completo

En definitiva, para buscar archivos de LibreOffice / OpenOffice, esos con extensión ODT:

Y para buscar archivos Office Open XML de Microsoft Word, esos con extensión DOCX:

También podría interesarte....


Volver a la Portada de Logo Paperblog