Operaciones y filtrado de archivos

La mayoría del trabajo de línea de comandos se realiza sobre archivos. En esta sección discutimos cómo mirar y filtrar el contenido de archivos, tomar la información necesaria de los archivos utilizando un único comando, y ordenar archivos.

cat, tail, head, tee: Comandos de impresión de archivos

Estos comandos tienen casi la misma sintaxis:

     nombre_del_comando [opciones] [archivo(s)]
    

y se pueden usar en una tubería. Todos se utilizan para imprimir parte de un archivo de acuerdo con ciertos criterios.

El utilitario cat concatena archivos e imprime en la salida estándar. Este es uno de los comandos más ampliamente utilizados. Usted puede usar:

     # cat /var/log/mail/info
    

para imprimir, por ejemplo, el contenido del archivo de registro de un demonio de correo a la salida estándar[15]. El comando cat tiene una opción muy útil (-n) que le permite escribir los números de todas las líneas de salida.

Algunos archivos, como los archivos de registro de los demonios (si es que están corriendo) por lo general son enormes en tamaño[16] y no es muy útil imprimirlos por completo en la pantalla. Por lo general Usted sólo necesita ver sólo el comienzo del archivo. Puede utilizar el comando head para hacerlo. El mismo imprime, de manera predeterminada, las 10 primeras líneas. Entonces, el comando

     # head /var/log/mail/info
    

imprimirá las 10 primeras líneas del archivo /var/log/mail/info. Si Usted desea mostrar sólo las 2 primeras líneas puede utilizar el comando siguiente:

     # head -n2 /var/log/mail/info
    

El comando tail es similar a head, pero imprime las últimas líneas de un archivo. Este comando:

     # tail /var/log/mail/info
    

imprime las últimas 10 líneas de /var/log/mail/info (tail lo hace de manera predeterminada) Al igual que con head Usted puede imprimir las últimas 2 líneas de este archivo:

     # tail -n2 /var/log/mail/info
    

También puede usar estos comandos juntos. Por ejemplo, si desea mostrar sólo las líneas 9 y 10, puede teclear:

     # head /var/log/mail/info | tail -n2
    

donde el comando head seleccionará las primeras 10 líneas de un archivo, las pasará por una tubería al comando tail quien luego seleccionará las últimas 2 líneas. De la misma manera, Usted puede seleccionar desde la línea número 20 hasta el final del archivo:

     # tail -n20 /var/log/mail/info | head -n1
    

En este ejemplo, le decimos a tail que seleccione las últimas 20 líneas y las pase por una tubería a head. Luego, el comando head imprime la primer línea de los datos obtenidos.

Supongamos que deseamos imprimir el resultado del último ejemplo y guardarlo en el archivo resultados.txt. El utilitario tee nos puede ayudar. La sintaxis del mismo es:

    tee [opciones] [archivo]
   

Ahora podemos cambiar el comando anterior de esta manera:

     # tail -n20 /var/log/mail/info | head -n1 | tee resultados.txt
    

Tomemos otro ejemplo. Deseamos seleccionar las últimas 20 líneas, guardarlas en el archivo resultados.txt, pero imprimir en pantalla sólo la primera de las 20 seleccionadas. Entonces, deberíamos teclear:

     # tail -n20 /var/log/mail/info | tee resultados.txt | head -n1
    

El comando tee posee una opción útil (-a) que le permite añadir los datos recibidos a un archivo existente.

Volvamos al comando tail. Por lo general, los archivos de registro varían dinámicamente debido a que el demonio constantemente añade acciones y eventos al archivo de registro. Entonces, si desea mirar interactivamente los cambios al archivo de registro puede aprovechar una de las opciones más útiles de tail, -f:

     # tail -f /var/log/mail/info
    

En este caso, todos los cambios en el archivo /var/log/mail/info se imprimirán de inmediato en la pantalla. Utilizar el comando tail con la opción -f es muy útil cuando desea saber cómo funciona su sistema. Por ejemplo, mirando a través del archivo de registro /var/log/messages, puede estar al tanto con los mensajes del sistema y varios demonios.

En la próxima sección veremos cómo podemos utilizar grep como filtro para separar los mensajes de Postfix de aquellos mensajes que provienen de otros servicios.

grep: Ubicar cadenas de caracteres en archivos

Ni el acrónimo (“General Regular Expression Parser”, Analizador General de Expresiones Regulares), ni el nombre son muy intuitivos, pero su uso es simple. grep busca el patrón pasado como argumento en uno o más archivos. La sintaxis es:

     grep [opciones] <patrón> [uno o más archivos]
    

Si se mencionan varios archivos, los nombres de los mismos precederán a cada línea que muestran los resultados que se corresponden con el criterio de búsqueda. Use la opción -h para ocultar estos nombres; use la opción -l para obtener sólo los nombres de archivo en los cuales se cumple la condición de búsqueda. El patrón es una expresión regular, aunque generalmente consiste en una palabra simple. Las opciones usadas más frecuentemente son las siguientes:

  • -i: realizar una búsqueda que ignore la capitalización. (es decir, que ignore la diferencia entre las mayúsculas y las minúsculas);

  • -v: búsqueda inversa. Mostrar las líneas que no se corresponden con el patrón;

  • -n: mostrar, para cada línea encontrada, el número de línea;

  • -w: le dice a grep que el patrón debe corresponderse con una palabra completa, es decir debe aparecer tal cual y no como parte de otra palabra.

Volvamos entonces a analizar el archivo de registro del demonio de correo. Deseamos encontrar todas las cadenas en el archivo /var/log/mail/info que contengan el patrón “postfix”. Entonces tecleamos este comando:

    # grep postfix /var/log/mail/info
   

El comando grep se puede utilizar en una tubería. Por lo tanto, podemos obtener el mismo resultado que en el ejemplo previo haciendo esto:

     # cat /var/log/mail/info | grep postfix
    

Si deseamos invertir las condiciones y seleccionar aquellas cadenas que no contienen el patrón “postfix”, utilizamos -v:

    # grep -v postfix /var/log/mail/info
   

Supongamos que deseamos encontrar todos los mensajes acerca de correos enviados satisfactoriamente. En este caso tenemos que filtrar todas las cadenas que fueron añadidas al archivo de registro por el demonio de correo (contiene el patrón “postfix”) y deben contener un mensaje acerca de el envío satisfactorio (“status=sent”):

     # grep postfix /var/log/mail/info | grep status=sent
    

En este caso se utiliza a grep dos veces. Esto es permisible, pero no es elegante. Podemos obtener el mismo resultado utilizando el utilitario fgrep. Ahora deseamos crear el archivo patrones.txt (utilice cualquier nombre) que contiene los patrones escritos en una columna. Se puede crear tal archivo de la manera siguiente:

     # echo -e 'status=sent\npostfix' > ./patrones.txt
    

Luego llamamos a un comando donde utilizamos el archivo patrones.txt con una lista de patrones y el utilitario fgrep en vez de la “doble llamada” a grep:

     # fgrep -f ./patrones.txt /var/log/mail/info
    

El archivo patrones.txt puede tener tantos patrones como Usted desee. Cada uno tiene que estar tecleado en una única línea. Por ejemplo, para seleccionar los mensajes acerca de los envíos satisfactorios de correo a peter@mandrakesoft.com, será suficiente añadir esta dirección electrónica en nuestro archivo patrones.txt:

     # echo 'peter@mandrakesoft.com' >> ./patterns.txt
    

y ejecutar el comando anterior.

Está claro que puede combinar grep con tail y head. Si deseamos encontrar los mensajes sobre los últimos menos un correo enviados a peter@mandrakesoft.com tecleamos:

     # fgrep -f ./patrones.txt /var/log/mail/info | tail -n2 | head
       -n1
    

Aquí aplicamos el filtro descrito arriba y colocamos el resultado en una tubería para los comandos tail y head. Estos últimos seleccionan los últimos valores menos uno de los datos recibidos.

wc: Calculando elementos en archivos

El comando wc (Word Count, Cuenta de palabras) se usa para calcular la cantidad de cadenas y palabras en archivos. También es útil para contar bytes, caracteres, y la longitud de la línea más larga. Su sintaxis es:

    wc [opciones] [archivo(s)]
   

Las siguientes opciones son útiles:

  • -l: imprimir la cantidad de líneas nuevas;

  • -w: imprimir la cantidad de palabras;

  • -m: imprimir el total de caracteres;

  • -c: imprimir la cantidad de bytes;

  • -L: imprimir la longitud de la línea más larga en el texto.

El comando wc imprime la cantidad de líneas nuevas, palabras y caracteres de manera predeterminada. Aquí tiene algunos ejemplos de uso:

Si deseamos encontrar la cantidad de usuarios en nuestro sistema, podemos teclear:

    $wc -l /etc/passwd
   

Si deseamos saber la cantidad de CPUs en nuestro sistema, tecleamos:

    $grep "model name" /proc/cpuinfo | wc -l
   

En la sección anterior obtuvimos una lista de mensajes acerca de correos enviados satisfactoriamente a las direcciones listadas en nuestro archivo ./patrones.txt. Si deseamos saber la cantidad de dichos mensajes, podemos redireccionar los resultados de nuestro filtro por una tubería al comando wc:

     # fgrep -f ./patrones.txt /var/log/mail/info | wc -l
    

y luego obtendremos el resultado deseado.

sort: Clasificando archivos

Aquí tiene la sintaxis de este poderoso utilitario de clasificación[17]:

    sort [opciones] [archivo(s)]
   

Consideremos clasificar parte de el archivo /etc/passwd. Como puede ver:

     $ cat /etc/passwd
    

el archivo /etc/passwd no está clasificado. Deseamos clasificarlo por el campo login. Entonces tecleamos:

     $ sort /etc/passwd
    

El comando sort clasifica datos de manera ascendente comenzando por el primer campo (en nuestro caso, el campo login) de manera predeterminada. Si deseamos clasificar los datos de manera descendente, usamos la opción -r:

     $ sort -r /etc/passwd
    

Cada usuario tiene su propio UID escrito en el archivo /etc/passwd. Clasifiquemos un archivo de manera ascendente con el campo UID:

     $ sort /etc/passwd -t":" -k3 -n
    

Aquí utilizamos las siguientes opciones de sort:

  • -t":": le dice a sort que el símbolo : es el separador de campos;

  • -k3: significa que la clasificación debe hacerse según la tercer columna;

  • -n: dice que la clasificación ocurrirá sobre datos numéricos, no alfabéticos.

Se puede hacer lo mismo de manera inversa:

     $ sort /etc/passwd -t":" -k3 -n -r
    

Note que sort tiene dos opciones importantes:

  • -u: realiza una clasificación estricta: los campos de clasificación duplicados se descartan;

  • -f: ignorar capitalización (trata a las minúsculas como mayúsculas)

Finalmente, si deseamos encontrar el usuario con el mayor UID podemos usar el comando siguiente:

     $ sort /etc/passwd -t":" -k3 -n | tail -n1
    

donde clasificamos al archivo /etc/passwd de manera ascendente de acuerdo a la columna UID, y redireccionamos el resultado por medio de una tubería al comando tail que imprime el primer valor de la lista clasificada.



[15] Algunos ejemplos de esta sección están basados en trabajo real con archivos de registro de algunos servidores (servicios, demonios) Debe asegurarse que syslogd esté corriendo (permite el registro de los demonios), también el demonio correspondiente (en este ejemplo Postfix) y que Usted trabaja como root. De todas formas, siempre puede aplicar nuestros ejemplos a otros archivos.

[16] Por ejemplo, el archivo /var/log/mail/info contiene información acerca de todos los correos enviados, mensajes acerca de la recuperación de correo por parte de los usuarios con el protocolo POP, etc.

[17] Discutimos a sort brevemente aquí debido a que se podrían escribir libros completos acerca de sus características.