En GNU/Linux tenemos dos comandos que suelen ir de la mano que permiten extraer los primeros y últimos elementos de un listado.
Su uso más habitual es extraer las primeras líneas de un fichero con head o las últimas con tail.
Veamos un ejemplo sencillo sobre un fichero de texto con "Un soneto me manda hacer Violante" de Lope de Vega:
head violante.txt
Un soneto me manda hacer Violante
que en mi vida me he visto en tanto aprieto;
catorce versos dicen que es soneto;
burla burlando van los tres delante.
Yo pensé que no hallara consonante,
y estoy a la mitad de otro cuarteto;
mas si me veo en el primer terceto,
no hay cosa en los cuartetos que me espante.
tail violante.txt
mas si me veo en el primer terceto,
no hay cosa en los cuartetos que me espante.
Por el primer terceto voy entrando,
y parece que entré con pie derecho,
pues fin con este verso le voy dando.
Ya estoy en el segundo, y aun sospecho
que voy los trece versos acabando;
contad si son catorce, y está hecho.
Por defecto y sin pasarle ningún argumento más que el fichero a listar, tanto tail como head muestran diez líneas. Head las diez primeras líneas, tail las diez últimas líneas.
Pero podemos cambiar el número de líneas a mostrar con -n $numerodelineas
Veamos el primer cuarteto:
head -4 violante.txt
Un soneto me manda hacer Violante
que en mi vida me he visto en tanto aprieto;
catorce versos dicen que es soneto;
burla burlando van los tres delante.
Y el último terceto:
tail -n 3 violante.txt
Ya estoy en el segundo, y aun sospecho
que voy los trece versos acabando;
contad si son catorce, y está hecho.
Otra posibilidad que le podemos decir a tail es que muestre desde una determinada línea hasta el final.
tail -n+13 violante.txt
pues fin con este verso le voy dando.
Ya estoy en el segundo, y aun sospecho
que voy los trece versos acabando;
contad si son catorce, y está hecho.
Y si en lugar de mostrar las primeras y las últimas líneas lo que queremos es mostrar líneas centrales, lo que vamos a indicarles es que trabajen juntos: head, muestra las X primeras líneas y se las das a tail, para que seleccione las Y últimas líneas que les pases. Algo así:
head -n 13 violante.txt | tail -n 8
Yo pensé que no hallara consonante,
y estoy a la mitad de otro cuarteto;
mas si me veo en el primer terceto,
no hay cosa en los cuartetos que me espante.
Por el primer terceto voy entrando,
y parece que entré con pie derecho,
pues fin con este verso le voy dando.
Extraer únicamente los x primeros o últimos caracteres
Ambos comandos tienen una opción, -c que le indican que, en lugar de trabajar con líneas trabajen con caracteres:
head -c 30 violante.txt
Un soneto me manda hacer Viola
tail -c 30 violante.txt
i son catorce, y está hecho.
Hacer que tail y head muestren el nombre del fichero
Para hacer que tail y head muestren el nombre del fichero, se lo indicaremos con -v:
tail -n+13 -v violante.txt
==> violante.txt <==
pues fin con este verso le voy dando.
Ya estoy en el segundo, y aun sospecho
que voy los trece versos acabando;
contad si son catorce, y está hecho.
Sin embargo, si lo que queremos es que no muestre el nombre del fichero, lo indicaremos con -q:
tail -n+13 -q violante.txt
pues fin con este verso le voy dando.
Ya estoy en el segundo, y aun sospecho
que voy los trece versos acabando;
contad si son catorce, y está hecho.
Esto es básicamente lo que ha estado haciendo hasta ahora, pero ¿qué pasaría si queremos mostrar extractos de varios ficheros?
Cómo mostrar extractos de varios ficheros
Le podemos indicar a head o a tail que muestren extractos de multiples ficheros, y aquí si que viene bien que indique el nombre del fichero. Quizá no en este ejemplo, ya que el nombre del fichero es la primera línea sin espacios, pero en otras ocasiones, sí.
head -v lope/*
==> lope/albaniayaceaquifabiosuspira.txt <==
Albania yace aquí, Fabio suspira,
matóla un parto sin sazón, dejando
la envidia alegre, y al Amor llorando;
pues ya cualquiera fuerza le retira.
El Tajo crece por mostrar su ira
y corre, de la Muerte murmurando;
párase el sol, el túmulo mirando,
temiendo en sí, lo que en Albania mira.
==> lope/amormilanoshaquemehasjurado.txt <==
Amor, mil años ha que me has jurado
pagarme aquella deuda en plazos breves;
mira que nunca pagas lo que debes,
que esto sólo no tienes de hombre honrado.
Muchas veces, Amor, me has engañado
con firmas falsas y esperanzas leves;
a estelionatos con mi fe te atreves,
jurando darme lo que tienes dado.
==> lope/laclaraluzenlasestrellaspuesta.txt <==
La clara luz en las estrellas puesta
del fogoso León por alta parte
bañaba el sol, cuando Acidalia y Marte
en Chipre estaban una ardiente siesta.
La diosa por hacerle gusto y fiesta
la túnica y el velo deja aparte,
sus armas toma y de la selva parte,
del yelmo y plumas y el arnés compuesta.
==> lope/violante.txt <==
Un soneto me manda hacer Violante
que en mi vida me he visto en tanto aprieto;
catorce versos dicen que es soneto;
burla burlando van los tres delante.
Yo pensé que no hallara consonante,
y estoy a la mitad de otro cuarteto;
mas si me veo en el primer terceto,
no hay cosa en los cuartetos que me espante.
==> lope/yanoquieromasbienquesoloamaros.txt <==
Ya no quiero más bien que sólo amaros
ni más vida, Lucinda, que ofreceros
la que me dais, cuando merezco veros,
ni ver más luz que vuestros ojos claros.
Para vivir me basta desearos,
para ser venturoso conoceros,
para admirar el mundo engrandeceros
y para ser Eróstrato abrasaros.
O le podemos decir que no muestre el nombre del fichero ni que separe las líneas de los distintos ficheros con -q. Veamos el último terceto de cada uno de estos sonetos sin nombre:tail -q -n 3 lope/*
Venganza fue para que ejemplo quede
que quien fue basilisco en dar veneno,
muriese como víbora en el parto.
Mas, ¿cómo pagarás, Amor, si has hecho
pleito de acreedores por mil años
y, en buscando tu hacienda, estás desnudo?
Venus le respondió: «Cuando te atrevas
verás cuanto mejor te vence armada
la que desnuda te venció primero».
Ya estoy en el segundo, y aun sospecho
que voy los trece versos acabando;
contad si son catorce, y está hecho.
Que entre tales riquezas y tesoros
mis lágrimas, mis versos, mis suspiros
de olvido y tiempo vivirán seguros.
Un poco lioso todo, pero para eso hemos elegido un autor barroco ;)
Más usos de tail y head
Mostrar el primer y último fichero de un directorio
Estos dos comandos nos permiten saber, por ejemplo, cuál es el primer y último fichero de un directorio:
ls lope/ | head -n 1
albaniayaceaquifabiosuspira.txt
ls lope/ | tail -n 1
yanoquieromasbienquesoloamaros.txt
Esto viene muy bien cuando numeramos los ficheros y queremos saber cuál es el último.
Supongamos que tenemos un directorio que se llame "fotogramas" con un número de fotogramas que desconocemos y queremos saber cuál es el último. Le podemos indicar en un script que lo extraiga y lo guarde en una variable:
ultimofotograma=$(ls $directoriofotogramas | tail -n 1)
Extraer colores consecutivos para hacer un degradado
Dentro de un bucle for, podemos ir cambiando el valor de head manteniendo tail constante a -n 1 y lo que harán será ir extrayendo uno a uno los elementos que le indiquemos.
Veamos un ejemplo:
#!/bin/bash
colores=""
for i in $(seq 1 5)
do
color=$(convert -list color | grep LightBlue | cut -d " " -f 1 | head -n $i | tail -n 1)
colores=$colores"xc:"$color" "
done
convert -size 500x100 $colores -append -motion-blur 0x100+90 celeste.png
Con este script generamos una imagen como esta:
Porque head y tail no sólo sirven para trabajar con ficheros de texto. También ayudan a hacer degradados ;)