← Terminal y Línea de Comandos en Linux Bloque 3 · Manipular archivos y directorios · Tema 12 de 43

Tema 12

Ver el contenido de un archivo

En Linux casi todo lo que importa es texto: la configuración, los registros, los scripts, los datos que intercambian los programas. Saber mirar un archivo de texto es, por eso, una de las tareas más frecuentes. Hay una herramienta para cada manera de mirar: el archivo entero, de a una pantalla, solo el comienzo, solo el final, o a medida que alguien lo va escribiendo. Elegir la adecuada es la diferencia entre encontrar un dato en segundos y ver pasar diez mil líneas por la pantalla.

1. Antes de abrir: texto o binario

Para el sistema, todos los archivos son lo mismo: una secuencia de bytes. La diferencia está en cómo se interpretan, y hay dos grandes familias:

Archivo de textoArchivo binario
Sus bytes representanLetras, números y signosDatos en un formato propio de cada programa
Se leeDirectamente, con cualquier herramientaSolo con el programa que conoce el formato
EjemplosConfiguración, registros, scripts, código fuente, CSV, HTMLProgramas, imágenes, audio, video, archivos comprimidos, PDF

Las herramientas de este tema son para archivos de texto. Como en Linux la extensión no garantiza nada, según vimos en el tema 6, hay un comando que averigua de qué clase es un archivo mirando su contenido: file.

terminal, en ~/practica
$ cd ~/practica
$ file notas.txt informe.txt fotos /usr/bin/ls
notas.txt:   ASCII text
informe.txt: ASCII text
fotos:       directory
/usr/bin/ls: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, …

file reconoce cientos de formatos: imágenes, con sus dimensiones; documentos, archivos comprimidos, y el idioma de codificación de los textos. Ante un archivo de origen dudoso, es lo primero que conviene ejecutar.

Si la terminal queda llena de símbolos raros

Mostrar un archivo binario con cat no lo daña, pero envía a la terminal bytes que esta interpreta como órdenes: la pantalla se llena de signos y el indicador puede quedar ilegible, con otros caracteres. Se arregla escribiendo reset y pulsando Enter, aunque no se vea lo que se teclea.

2. cat: el archivo entero

cat escribe en la pantalla el contenido completo de los archivos que recibe, uno después de otro. Lo usamos desde el tema 2:

terminal
$ cat notas.txt
Mi primer archivo
$ cat notas.txt /etc/hostname       # dos archivos, uno a continuación del otro
Mi primer archivo
equipo

El segundo ejemplo explica el nombre, que viene de concatenate, encadenar. cat se creó para unir archivos; mostrar uno solo es el caso más simple de esa unión. Junto con una redirección, que veremos en el tema 23, sirve para fundir varios archivos en uno.

OpciónEfecto
-nNumera las líneas.
-bNumera solo las líneas que no están vacías.
-sReduce varias líneas vacías seguidas a una sola.
-AMuestra los caracteres invisibles: tabulaciones y finales de línea.

cat tiene un límite evidente: no se detiene. Con un archivo de pocas líneas es ideal; con uno largo, el contenido pasa a toda velocidad y solo queda a la vista el final. Si lo ejecutas sobre un archivo enorme por error, Ctrl+C lo interrumpe.

cat es adecuado para…No lo es para…
Archivos que entran en una pantalla.Archivos largos: para eso está less.
Unir varios archivos.Ver solo una parte: head y tail.
Enviar un archivo a otro comando.Archivos binarios.

3. Qué es una línea

Todas las herramientas de este tema, y casi todas las del bloque 6, trabajan por líneas. Conviene saber con precisión qué es una.

Una línea es una secuencia de caracteres terminada por un carácter especial, el salto de línea. Ese carácter no se ve, pero ocupa un byte en el archivo, igual que una letra.

La opción -A de cat lo hace visible, representándolo con un signo $ al final de cada línea:

terminal
$ cat -A notas.txt
Mi primer archivo$
$ ls -l notas.txt
-rw-rw-r-- 1 ana ana 18 oct 12 10:32 notas.txt

Esto resuelve una pequeña incógnita que arrastramos desde el tema 2. «Mi primer archivo» tiene 17 caracteres, contando los espacios, y el archivo mide 18 bytes: el que falta es el salto de línea que echo agregó al final.

-A muestra también las tabulaciones, como ^I. Es la manera de saber si las columnas de un archivo están separadas con espacios o con tabuladores, cosa que a simple vista no se distingue y que importa al procesarlo:

terminal: la novena línea de informe.txt, con los invisibles a la vista
$ head -n 9 informe.txt | tail -n 1 | cat -A
tcpmux^I^I1/tcp^I^I^I^I# TCP port service multiplexer$

La misma opción diagnostica un problema clásico. Windows termina cada línea con dos caracteres en lugar de uno. Un archivo de texto creado allí y llevado a Linux se ve bien, pero cada línea termina en ^M$ en vez de $, y ese carácter sobrante hace fallar a los scripts con errores incomprensibles. Se corrige con el comando dos2unix.

4. less: leer de a una pantalla

Para un archivo que no entra en la pantalla, la herramienta es un paginador. Ya lo conocemos: es el programa que man usa para mostrar sus páginas, y que en el tema 4 usamos también con --help. Se llama less, y abre cualquier archivo:

terminal
$ less informe.txt

La pantalla se llena con el comienzo del archivo y en la última línea aparece su nombre. Las teclas son las que aprendimos para el manual:

TeclaAcción
Barra espaciadora, bAvanzar y retroceder una pantalla.
FlechasMoverse de a una línea.
g, GIr al principio y al final.
/texto, ?textoBuscar hacia adelante y hacia atrás.
n, NCoincidencia siguiente y anterior.
qSalir.

less tiene tres ventajas sobre cat que lo hacen la opción por defecto para cualquier archivo que no sea mínimo. Permite ir hacia atrás. Permite buscar. Y no carga el archivo entero antes de mostrarlo: abre al instante un registro de varios gigabytes.

El nombre es una broma. El paginador original de Unix se llamaba more, «más», por el aviso que mostraba al pie de cada pantalla, y solo avanzaba. Cuando se escribió uno mejor, que también retrocedía, lo llamaron less, por el dicho less is more, «menos es más». more sigue existiendo, pero no hay motivo para preferirlo.

5. less, más allá de lo básico

Algunas funciones de less resultan muy útiles con archivos reales y no hacían falta para leer el manual:

Dentro de lessAcción
50gIr a la línea 50.
50%Ir a la mitad del archivo.
&textoMostrar solo las líneas que contienen ese texto. & y Enter las vuelve a mostrar todas.
-NActivar o quitar los números de línea.
-SActivar o quitar el corte de líneas largas: en lugar de doblarse, siguen hacia la derecha y se recorren con las flechas laterales.
-iHacer que las búsquedas no distingan mayúsculas de minúsculas.
FEsperar y mostrar lo que se agregue al archivo. Ctrl+C vuelve al modo normal.
hLa ayuda completa.

Las que empiezan con guion son a la vez opciones de la línea de comandos: se pueden teclear dentro de less, o escribir al abrirlo.

terminal
$ less -N informe.txt               # con números de línea
$ less -S /var/log/syslog           # sin doblar las líneas largas
$ less +G /var/log/syslog           # abrir directamente al final
$ less +/ssh informe.txt            # abrir en la primera aparición de «ssh»

El filtro & es el menos conocido y uno de los más prácticos: en un registro de miles de líneas, &error deja a la vista solo las que mencionan un error, y se sigue pudiendo navegar y buscar entre ellas.

-S merece una explicación. Un registro o una tabla de datos suele tener líneas más anchas que la ventana. Dobladas, cada registro ocupa varios renglones y las columnas se desarman. Cortadas, cada línea del archivo ocupa un renglón de la pantalla, y la estructura vuelve a verse.

Muchas veces alcanza con el comienzo de un archivo para saber qué es y qué formato tiene. head muestra las primeras líneas; diez, si no se indica otra cosa:

terminal
$ head informe.txt
# Network services, Internet style
#
# Updated from https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml .
#
# New ports will be added on request if they have been officially assigned
# by IANA and used in the real-world or are needed by a debian package.
# If you need a huge list of used numbers please install the nmap package.

tcpmux          1/tcp                           # TCP port service multiplexer
echo            7/tcp

Diez líneas bastaron para entender el archivo: un encabezado de comentarios que explica su origen, y luego una tabla con el nombre de cada servicio de red, su número de puerto y, a veces, una descripción.

ComandoMuestra
head archivoLas primeras 10 líneas.
head -n 3 archivoLas primeras 3.
head -3 archivoLo mismo, en la forma abreviada.
head -n -5 archivoTodo menos las últimas 5.
head -c 100 archivoLos primeros 100 bytes, sin atender a las líneas.

Con varios archivos, head muestra el comienzo de cada uno, precedido de un título con su nombre. Es una forma rápida de pasar revista a un directorio:

terminal
$ head -n 1 *.txt
==> informe.txt <==
# Network services, Internet style

==> notas.txt <==
Mi primer archivo

7. tail: el final

tail es el complemento: muestra las últimas líneas. Diez, por defecto.

terminal
$ tail -n 5 informe.txt
dircproxy       57000/tcp                       # Detachable IRC Proxy
tfido           60177/tcp                       # fidonet EMSI over telnet
fido            60179/tcp                       # fidonet EMSI over TCP

# Local services

El final es la parte que más interesa en los registros. Un programa que anota lo que hace agrega cada novedad al final de su archivo, de modo que lo último que ocurrió está en las últimas líneas. Ante una falla, tail sobre el registro correspondiente es el primer gesto.

ComandoMuestra
tail archivoLas últimas 10 líneas.
tail -n 3 archivoLas últimas 3.
tail -n +20 archivoDesde la línea 20 hasta el final.
tail -c 100 archivoLos últimos 100 bytes.

La tercera fila tiene una sintaxis que se presta a confusión, y que conviene mirar junto con su simétrica de head. En los dos comandos, un signo delante del número cambia el punto de referencia:

Se escribeSignificaUso típico
head -n 5Las 5 primeras.Ver el comienzo.
head -n -5Todas, salvo las 5 últimas.Quitar un pie de página.
tail -n 5Las 5 últimas.Ver el final.
tail -n +5Todas, a partir de la quinta.Quitar un encabezado.

El último caso es muy frecuente con archivos de datos, cuya primera línea contiene los títulos de las columnas: tail -n +2 datos.csv entrega todo salvo esa línea.

8. Un tramo del medio

No hay un comando para «las líneas 10 a 12». No hace falta: se obtienen combinando los dos anteriores con una tubería, de modo que la salida del primero sea la entrada del segundo.

terminal: dos maneras de obtener las líneas 10 a 12
$ head -n 12 informe.txt | tail -n 3     # las 12 primeras, y de ellas las 3 últimas
echo            7/tcp
echo            7/udp
discard         9/tcp           sink null
$ tail -n +10 informe.txt | head -n 3    # desde la 10, y de ellas las 3 primeras
echo            7/tcp
echo            7/udp
discard         9/tcp           sink null

El ejemplo es pequeño, y muestra la manera de pensar de la terminal: en lugar de un comando grande que lo haga todo, dos comandos simples, cada uno con una tarea, conectados. Las tuberías son el tema 24, y a esta altura ya las usamos varias veces sin ceremonia.

Con cat -n delante se puede comprobar el resultado, porque cada línea llega con su número: cat -n informe.txt | head -n 12 | tail -n 3. Más adelante veremos una herramienta que extrae un rango de líneas directamente, sed, en el tema 29.

9. tail -f: seguir un archivo en vivo

tail tiene una opción que lo convierte en otra herramienta. Con -f, de follow, muestra las últimas líneas y no termina: se queda esperando, y escribe cada línea nueva en el momento en que alguien la agrega al archivo.

Para verlo hacen falta dos terminales. En la primera se sigue un archivo; en la segunda se le agregan líneas. Usamos /tmp, para no dejar rastros:

terminal 1
$ touch /tmp/diario.log
$ tail -f /tmp/diario.log
                                    ← queda esperando, sin indicador
terminal 2
$ echo "Arranca el servicio" >> /tmp/diario.log
$ echo "Conexión aceptada" >> /tmp/diario.log
terminal 1, al mismo tiempo
$ tail -f /tmp/diario.log
Arranca el servicio
Conexión aceptada

Cada línea aparece en la primera terminal en el instante en que se ejecuta el echo en la segunda. Los dos signos >> agregan texto al final de un archivo; los explicamos en el tema 23. Para terminar el seguimiento se pulsa Ctrl+C: es el caso, anunciado en el tema 2, de un comando que no termina por sí solo.

Este es el modo en que se observa un sistema en funcionamiento. Se deja un tail -f sobre el registro de un servicio en una ventana, se provoca la situación a estudiar en otra, y se lee lo que el servicio va anotando mientras ocurre.

ComandoEfecto
tail -f archivoSigue el archivo.
tail -n 50 -f archivoMuestra las últimas 50 líneas y luego sigue.
tail -n 0 -f archivoSolo lo nuevo, sin mostrar nada de lo anterior.
tail -F archivoSigue el nombre: si el archivo se reemplaza por uno nuevo, continúa con el nuevo.
tail -f a.log b.logSigue varios a la vez, indicando de cuál viene cada línea.

La -F mayúscula es la que conviene para los registros del sistema. Estos se rotan periódicamente: el archivo actual se guarda con otro nombre y se empieza uno nuevo, vacío. Un tail -f se quedaría mirando el viejo, en silencio; -F se da cuenta y pasa al nuevo.

Dentro de less, la tecla F hace lo mismo, con la ventaja de que Ctrl+C devuelve al paginador y se puede retroceder y buscar en lo que pasó.

10. wc: contar

wc, de word count, no muestra el contenido de un archivo sino sus dimensiones:

terminal
$ wc notas.txt
 1  3 18 notas.txt
$ wc informe.txt
  361  1773 12813 informe.txt
anatomía de la salida de wc
  361  1773 12813 informe.txt
  │    │    │     │
  │    │    │     └─ el archivo
  │    │    └─ bytes
  │    └─ palabras
  └─ líneas

Los tres números son siempre líneas, palabras y bytes, en ese orden. Una «palabra» es cualquier secuencia de caracteres separada por espacios, tabulaciones o saltos de línea. Con opciones se pide uno solo:

OpciónCuenta
-lLíneas. Es, con mucha diferencia, la más usada.
-wPalabras.
-cBytes.
-mCaracteres.
-LLa longitud de la línea más larga.
terminal
$ wc -l *.txt
  361 informe.txt
    1 notas.txt
  362 total
$ echo "año" | wc -c                # bytes
5
$ echo "año" | wc -m                # caracteres
4

Con varios archivos, wc agrega una línea con el total. Los dos últimos comandos muestran la diferencia entre bytes y caracteres, que anticipamos al hablar de los nombres en el tema 6. La palabra «año» tiene tres letras, más el salto de línea que añade echo: cuatro caracteres. Pero la ñ ocupa dos bytes, y por eso son cinco. En un texto en español, -c y -m dan números distintos.

wc -l cuenta en rigor los saltos de línea. Por eso un archivo cuya última línea no termina en salto de línea da uno menos de lo esperado. Es raro, y explica alguna diferencia de una unidad.

11. También leen de una tubería

En varios ejemplos estos comandos no recibieron un nombre de archivo, sino la salida de otro comando. Es una propiedad común a todos, y la que los hace tan útiles:

Cuando no se les indica un archivo, cat, less, head, tail y wc leen de su entrada. Conectados con una tubería a otro comando, procesan lo que este escribe como si fuera un archivo.

ComandoQué se obtiene
ls -l /etc | lessUn listado largo, leído de a una pantalla.
ls /usr/bin | wc -lCuántos programas hay en ese directorio.
ls -lS /var/log | head -n 6Los archivos más grandes: el total y las cinco primeras líneas.
history | tail -n 20Los últimos veinte comandos.
find ~ -type f | wc -lCuántos archivos hay en el directorio personal.

De ahí salen tres costumbres que conviene adquirir. Cuando un comando produce más de una pantalla, | less al final. Cuando solo interesa cuántos resultados hay, | wc -l. Y cuando interesa una muestra, | head.

Hay una diferencia de salida que ya apareció en la sección anterior: leyendo de una tubería, wc no muestra ningún nombre, porque no hay archivo que nombrar. Solo el número, que es lo cómodo para usarlo en un script.

12. Otras formas de mirar

Algunas herramientas menores completan el repertorio. No hace falta memorizarlas; sí saber que existen:

ComandoQué hacePara qué sirve
nl archivoNumera las líneas, como cat -b, con más control del formato.Preparar un texto para citar líneas.
tac archivoMuestra el archivo con las líneas en orden inverso: es cat al revés.Leer un registro empezando por lo más reciente.
zcat, zlessLo mismo que cat y less, sobre archivos comprimidos .gz.Leer los registros antiguos de /var/log sin descomprimirlos.
strings archivoExtrae los fragmentos de texto legible que hay dentro de un binario.Espiar qué mensajes contiene un programa.
xxd archivoMuestra los bytes en hexadecimal, junto a su equivalente en texto.Examinar un binario, o un texto con caracteres extraños.

La última permite ver por dentro lo que cat no puede mostrar. Las primeras posiciones de un programa de Linux, por ejemplo:

terminal
$ head -c 16 /usr/bin/ls | xxd
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............

A la izquierda, la posición; en el centro, los dieciséis bytes en hexadecimal; a la derecha, los que corresponden a un carácter visible, y un punto en lugar de los demás. Los cuatro primeros son una marca que identifica el formato: las letras ELF, el de los ejecutables de Linux. Así trabaja el comando file de la sección 1: reconoce las marcas del comienzo de cada archivo.

13. Explorar un archivo desconocido

Con todas las piezas se puede fijar un procedimiento para la situación más habitual: alguien te pasa un archivo, o lo encuentras en un directorio del sistema, y quieres saber qué es sin sorpresas.

  1. Tamaño y fecha, con ls -lh archivo. ¿Son kilobytes o gigabytes? medir
  2. Tipo, con file archivo. Si no es texto, las herramientas de este tema no sirven. identificar
  3. Cantidad de líneas, con wc -l archivo. medir
  4. El principio, con head archivo. Suele explicar el formato. mirar
  5. El final, con tail archivo. En un registro, es lo más reciente. mirar
  6. El resto, con less archivo, buscando con / lo que interese. leer

Aplicado a nuestro archivo de práctica, los cinco primeros pasos dicen: 13 KB, texto, 361 líneas, un encabezado de comentarios seguido de una tabla de servicios y puertos, y una sección final vacía para servicios locales. En menos de un minuto, y sin haber leído el archivo, se sabe qué es y cómo está organizado.

Y el criterio para elegir herramienta:

Quiero…Comando
Saber qué clase de archivo esfile archivo
Ver un archivo cortocat archivo
Leer un archivo largo, o buscar en élless archivo
Ver cómo empiezahead archivo
Ver lo último que se escribiótail archivo
Ver lo que se va escribiendotail -f archivo
Saltear la primera líneatail -n +2 archivo
Ver las líneas 20 a 30head -n 30 archivo | tail -n 11
Saber cuántas líneas tienewc -l archivo
Ver espacios, tabulaciones y finales de líneacat -A archivo

El archivo /tmp/diario.log de la sección 9 puede quedar donde está: desaparecerá al reiniciar.

Mirar es la mitad del trabajo con texto. La otra mitad es cambiarlo. En el tema 13 aprendemos a editar un archivo sin salir de la terminal, con nano, y lo indispensable de vim.

14. Resumen

15. Preguntas de repaso

Intenta responder cada una antes de abrir la respuesta.

1. ¿Cómo se averigua si un archivo es de texto antes de mostrarlo?

Con file archivo, que examina el contenido e informa el tipo.

2. Mostraste un binario con cat y la terminal quedó ilegible. ¿Qué haces?

Escribir reset y pulsar Enter, aunque no se vea lo que se teclea. Restablece la terminal.

3. ¿De dónde viene el nombre cat y qué hace con varios archivos?

De concatenate. Muestra los archivos uno a continuación del otro, como si fueran uno solo.

4. El archivo notas.txt contiene un texto de 17 caracteres y mide 18 bytes. ¿Qué es el byte restante?

El salto de línea que termina la única línea del archivo. Se lo puede ver con cat -A, que lo representa con un signo $.

5. ¿Qué ventajas tiene less sobre cat para un archivo largo?

Muestra de a una pantalla, permite retroceder y buscar, y no necesita leer el archivo entero antes de empezar.

6. Dentro de less, ¿cómo se muestran solo las líneas que contienen la palabra «error»?

Con &error y Enter. Un & solo, seguido de Enter, vuelve a mostrar todas.

7. ¿Qué muestran head -n 3 y tail -n 3?

Las tres primeras líneas y las tres últimas, respectivamente.

8. ¿Qué diferencia hay entre tail -n 5 y tail -n +5?

La primera muestra las últimas cinco líneas. La segunda, todas las líneas a partir de la quinta.

9. Escribe un comando que muestre las líneas 50 a 60 de un archivo.

head -n 60 archivo | tail -n 11, o bien tail -n +50 archivo | head -n 11.

10. ¿Qué hace tail -f y cómo se termina?

Muestra las últimas líneas del archivo y queda esperando, escribiendo cada línea nueva que se le agrega. Se termina con Ctrl+C.

11. ¿Cuándo conviene tail -F en lugar de tail -f?

Con los registros que se rotan. Si el archivo se reemplaza por uno nuevo con el mismo nombre, -F pasa a seguir el nuevo, mientras que -f seguiría mirando el anterior.

12. ¿Qué significan los tres números de wc archivo?

La cantidad de líneas, de palabras y de bytes, en ese orden.

13. ¿Por qué wc -c y wc -m pueden dar resultados distintos?

Porque -c cuenta bytes y -m cuenta caracteres. Las letras con tilde y la ñ ocupan más de un byte cada una.

14. ¿Cómo se cuenta cuántos archivos hay en un directorio?

Enviando el listado a wc -l: ls directorio | wc -l. Para incluir los subdirectorios, find directorio -type f | wc -l.

15. ¿Qué pasos conviene seguir ante un archivo desconocido?

Ver su tamaño con ls -lh, su tipo con file, su cantidad de líneas con wc -l, su principio con head, su final con tail, y recién entonces abrirlo con less.

Para practicar

  1. Ejecuta file sobre /etc/passwd, /usr/bin/bash, /etc, /bin y algún archivo de /usr/share/man/man1. ¿Qué tipo informa para cada uno?
  2. Aplica el método de la sección 13 a /etc/passwd. ¿Cuántas líneas tiene, y qué separa sus campos?
  3. Abre informe.txt con less -N. Ve a la línea 100, busca http, recorre las coincidencias, y luego filtra con &udp.
  4. Muestra las líneas 20 a 25 de informe.txt con sus números, usando cat -n, head y tail.
  5. Muestra informe.txt sin su encabezado de comentarios, es decir, a partir de la línea 9, y cuenta cuántas líneas quedan.
  6. Con cat -A, averigua si /etc/passwd y /etc/fstab usan tabulaciones o espacios.
  7. Repite la experiencia de la sección 9 con dos terminales. Prueba luego tail -n 0 -f y observa la diferencia.
  8. Si tu usuario puede leerlo, ejecuta tail -f /var/log/syslog y, en otra terminal, logger "Hola desde la terminal". ¿Qué aparece?
  9. Averigua cuántas páginas tiene la sección 1 del manual contando los archivos de /usr/share/man/man1.
  10. Compara echo "canción" | wc -c con echo "cancion" | wc -c y explica la diferencia. Luego mira los bytes con echo "ñ" | xxd.