Continuando con el recorrido por los comandos no tan conocidos que comenzamos la semana pasada con el comando ls, examinemos hoy el cat
comando.
El cat
nombre significa catenate
ya que el trabajo principal de ese comando es unir varios archivos de entrada enviando secuencialmente su contenido en la salida estándar:
# Let's obtain first some sample data files:
curl -so - dict://dict.org/'d:felidae:gcide' | unexpand -a -t 3 |
sed -Ee '/^151/,/^[.]/!d;/^[.0-9]/s/.*//' > felidae.txt
curl -so - dict://dict.org/'d:felis:gcide' | unexpand -a -t 3 |
sed -Ee '/^151/,/^[.]/!d;/^[.0-9]/s/.*//' > felis.txt
# Catenate files
cat felidae.txt felis.txt
Si desea almacenar el resultado de esa concatenación en un archivo, debe usar una redirección de shell:
cat felidae.txt felis.txt > result.txt
cat result.txt
Incluso si su principal objetivo de diseño es encadenar archivos, el cat
La utilidad también se emplea a menudo con un solo argumento para mostrar el contenido de ese archivo en la pantalla, exactamente como lo hice en la última línea del ejemplo anterior.
A. Usando el comando cat con entrada estándar
Cuando se usa sin ningún argumento, el cat
El comando leerá los datos de su entrada estándar y los escribirá en su salida estándar, lo que en su mayoría es inútil... a menos que esté usando alguna opción para transformar los datos. Hablaremos de un par de opciones interesantes más adelante.
Además de las rutas de archivo, el cat
El comando también entiende el -
nombre de archivo especial como un alias para la entrada estándar. De esa forma, puede insertar los datos leídos desde la entrada estándar entre los archivos proporcionados en la línea de comando:
# Insert a separator between the two concatenated files
echo '----' | cat felis.txt - felidae.txt
B. Usando el comando cat con archivos binarios
1. Unirse a archivos divididos
El cat
El comando no hace ninguna suposición sobre el contenido del archivo, por lo que funcionará felizmente con datos binarios. Algo que puede ser útil para volver a unir archivos rotos por el split
o csplit
dominio. O para unir descargas parciales como lo haremos ahora:
#
# A picture by Von.grzanka (CC-SA 3.0)
# Optimize bandwidth usage by breaking the download in two parts
# (on my system, I observe a 10% gain that way compared to a "full" download)
curl -s -r 0-50000 \
https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Felis_catus-cat_on_snow.jpg/1024px-Felis_catus-cat_on_snow.jpg \
-o first-half &
curl -s -r 50001- \
https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Felis_catus-cat_on_snow.jpg/1024px-Felis_catus-cat_on_snow.jpg \
-o second-half &
wait
Ahora tenemos dos mitades de una imagen. Puede abrir la primera mitad y ver que está "rota" usando la display
de ImageMagick , o gimp
, o cualquier otro software capaz de leer archivos de imagen:
display first-half
# -or-
gimp first-half
# -or-
firefox first-half
Si estudias el curl
comando que usé, ves que las dos partes son perfectamente complementarias. La primera mitad es del byte 0 al 50000 y la segunda mitad, del byte 50001 al final del archivo. No debe haber datos faltantes entre ellos. Así que solo tenemos que catenar las dos partes juntas (en el orden correcto) para recuperar el archivo completo:
cat first-half second-half > image.jpg
display image.jpg
2. Trabajar con formatos de archivo que se pueden transmitir
No solo puedes usar el cat
comando para "volver a unir" archivos binarios que se dividieron en varias partes, pero en algunos casos, también puede crear nuevo archivos de esa manera. Eso funciona particularmente bien con formatos de archivo "sin encabezado" o "transmitibles" como archivos de video de flujo de transporte MPEG (.TS
archivos):
# Let's make a still video file from our picture
ffmpeg -y -loop 1 -i cat.jpg -t 3 \
-c:v libx264 -vf scale=w=800:h=-1 \
still.ts
# Let's make a fade-in from the same picture
ffmpeg -y -loop 1 -i cat.jpg -t 3 \
-c:v libx264 -vf scale=w=800:h=-1,fade=in:0:75 \
fadein.ts
# Let's make a fade-out from the same picture
ffmpeg -y -loop 1 -i cat.jpg -t 3 \
-c:v libx264 -vf scale=w=800:h=-1,fade=out:0:75 \
fadeout.ts
Ahora podemos combinar todos esos archivos de video de flujo de transporte usando el cat
comando, obteniendo un archivo TS perfectamente válido en la salida:
cat fadein.ts still.ts fadeout.ts > video.ts
mplayer video.ts
Gracias al formato de archivo TS, puede combinar esos archivos en el orden que desee, e incluso puede usar el mismo archivo varias veces en la lista de argumentos para crear bucles o repeticiones en el video de salida. Obviamente, esto sería más divertido si usáramos imágenes animadas, pero te dejaré hacerlo por ti mismo:muchos dispositivos de nivel de consumidor graban archivos TS y, si no lo hacen, aún puedes usar ffmpeg
para convertir casi cualquier archivo de video en un archivo de flujo de transporte. ¡No dudes en compartir tus creaciones usando la sección de comentarios!
3. Hackear archivos cpio
Como último ejemplo, veamos cómo podemos usar el cat
comando para combinar varios cpio
archivo. Pero esta vez, no será tan sencillo ya que requerirá un poco de conocimiento sobre el cpio
formato de archivo de almacenamiento.
Un cpio
El archivo almacena los metadatos y el contenido del archivo de forma secuencial, lo que lo hace adecuado para la concatenación a nivel de archivo con cat
utilidad. Desafortunadamente, el cpio
El archivo también contiene un tráiler utilizado para marcar el final del archivo:
# Create two genuine CPIO `bin` archive:
$ find felis.txt felidae.txt | cpio -o > part1.cpio
2 blocks
$ echo cat.jpg | cpio -o > part2.cpio
238 blocks
$ hexdump -C part1.cpio | tail -7
000002d0 2e 0d 0a 09 09 20 20 5b 57 6f 72 64 4e 65 74 20 |..... [WordNet |
000002e0 31 2e 35 5d 0d 0a 0a 00 c7 71 00 00 00 00 00 00 |1.5].....q......|
000002f0 00 00 00 00 01 00 00 00 00 00 00 00 0b 00 00 00 |................|
00000300 00 00 54 52 41 49 4c 45 52 21 21 21 00 00 00 00 |..TRAILER!!!....|
00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000400
$ hexdump -C part2.cpio | tail -7
0001da40 46 96 ab f8 ad 11 23 90 32 79 ac 1f 8f ff d9 00 |F.....#.2y......|
0001da50 c7 71 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |.q..............|
0001da60 00 00 00 00 0b 00 00 00 00 00 54 52 41 49 4c 45 |..........TRAILE|
0001da70 52 21 21 21 00 00 00 00 00 00 00 00 00 00 00 00 |R!!!............|
0001da80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
0001dc00
La buena noticia es que, con los archivos binarios de cpio, ese tráiler tiene una longitud fija de 280 bytes. Entonces, usando el head
comando estándar, tenemos una manera fácil de eliminarlo:
# Each archive end with the 280-byte trailer.
# To catenate both archives, just remove the trailer
# at the end of the first part:
$ head -c-280 part1.cpio | cat - part2.cpio > cat.cpio
$ cpio -it < cat.cpio
felis.txt
felidae.txt
cat.jpg
239 blocks
C. Opciones esenciales de comando cat
Después de haber jugado con varios formatos de archivos binarios, volvamos ahora a los archivos de texto simples estudiando un par de opciones diseñadas específicamente para manejar esos archivos. Si bien no forman parte del estándar POSIX, esas opciones son portátiles a través de BSD y GNU cat
implementaciones. Tenga en cuenta que no pretendo ser exhaustivo aquí, así que verifique el man
para ver la lista completa de opciones admitidas por cat
en su sistema!
-n
:rectas numéricas
Con el n
opción, el cat
El comando prefijará cada línea de salida por su número de línea:
cat -n felidae.txt
1
2 Felidae \Felidae\ n.
3 a natural family of lithe-bodied round-headed fissiped
4 mammals, including the cats; wildcats; lions; leopards;
5 cheetahs; and saber-toothed tigers.
6
7 Syn: family {Felidae}.
8 [WordNet 1.5]
9
El -n
números de opción salida líneas. Eso significa que el contador no restablecer al cambiar de un archivo de entrada al siguiente, como lo verá si prueba el siguiente comando usted mismo:
cat -n feli*.txt
-s
:suprimir líneas de salida vacías repetidas
Con -s
opción, el cat
El comando colapsará varias líneas vacías consecutivas en una sola:
cat -n felis.txt felidae.txt | sed -n 8,13p
8 lynx ({Felis lynx}) is also called {Lynx lynx}.
9 [1913 Webster +PJC]
10
11
12 Felidae \Felidae\ n.
13 a natural family of lithe-bodied round-headed fissiped
[email protected]:~$ cat -ns felis.txt felidae.txt | sed -n 8,13p
8 lynx ({Felis lynx}) is also called {Lynx lynx}.
9 [1913 Webster +PJC]
10
11 Felidae \Felidae\ n.
12 a natural family of lithe-bodied round-headed fissiped
13 mammals, including the cats; wildcats; lions; leopards;
En el ejemplo anterior, puede ver, en la salida predeterminada, las líneas 10 y 11 estaban vacías. Al agregar el -s
opción, la segunda línea vacía fue descartada.
-b
:número solo líneas no vacías
Algo relacionado con las dos opciones anteriores, el -b
opción numerará líneas, pero ignorando las vacías:
$ cat -b felidae.txt | cat -n
1
2 1 Felidae \Felidae\ n.
3 2 a natural family of lithe-bodied round-headed fissiped
4 3 mammals, including the cats; wildcats; lions; leopards;
5 4 cheetahs; and saber-toothed tigers.
6 5
7 6 Syn: family {Felidae}.
8 7 [WordNet 1.5]
9
El ejemplo anterior usa dos instancias de cat
Comando con diferentes opciones en una canalización. La numeración interna proviene de -b
opción usada con el primer cat
dominio. La numeración exterior proviene de -n
opción utilizada con el segundo cat
.
Como puede ver, la primera y la última línea fueron not numerado por -b
opción porque están vacíos. Pero, ¿qué pasa con la sexta línea? ¿Por qué todavía se numera con -b
? ¿opción? Bueno, porque es un espacio en blanco línea, pero no un vacío uno, como veremos en la siguiente sección.
-v
, -e
, -t
:mostrar caracteres no imprimibles
Las tres opciones -v
, -e `, and `-t
se utilizan para mostrar diferentes conjuntos de caracteres invisibles. Incluso si los conjuntos se superponen, no existe una opción "catch-all", por lo que tendrá que combinarlos si desea mostrar todos caracteres invisibles.
-v
:ver caracteres invisibles
El -v
opción mostrar todos los caracteres no imprimibles con intercalación y metanotación, excepto el salto de línea y la tabulación.
Con esa opción, los caracteres de control aparecerán como un signo de intercalación (^
) seguido del carácter ASCII apropiado (por ejemplo, el retorno de carro, byte 13, se muestra como ^M
porque M
en ASCII es 64 + 13), y los caracteres con el conjunto de bits de orden superior aparecerán en notación "meta" M-
seguido de la representación correspondiente a los 7 bits inferiores (por ejemplo, el byte 141 se mostrará como M-^M
porque 141 es 128 + 13).
Aunque aparentemente esotérica, esa característica puede ser útil cuando se trabaja con archivos binarios, como, por ejemplo, si desea examinar la información sin procesar incrustada en un archivo JPEG:
$ cat -v cat.jpg | fold -75 | head -10
M-^?M-XM-^?M-`^@^PJFIF^@^A^A^A^@H^@H^@^@M-^?M-~^@QFile source: http://commo
ns.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpgM-^?M-b^LXICC_PROFILE
^@^A^A^@^@^LHLino^B^P^@^@mntrRGB XYZ ^GM-N^@^B^@ ^@^F^@1^@^@acspMSFT
^@^@^@^@IEC sRGB^@^@^@^@^@^@^@^@^@^@^@^@^@^@M-vM-V^@^A^@^@^@^@M-S-HP ^@^@^
@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^@^@^@^@^@^Qcprt^@^@^AP^@^@^@3desc^@^@^AM-^D^@^@^@lwtpt^@^@^AM-p^@^@^@^
Tbkpt^@^@^B^D^@^@^@^TrXYZ^@^@^B^X^@^@^@^TgXYZ^@^@^B,^@^@^@^TbXYZ^@^@^[email protected]^@^@
^@^Tdmnd^@^@^BT^@^@^@pdmdd^@^@^BM-D^@^@^@M-^Hvued^@^@^CL^@^@^@M-^Fview^@^@^
CM-T^@^@^@$lumi^@^@^CM-x^@^@^@^Tmeas^@^@^D^L^@^@^@$tech^@^@^D0^@^@^@^LrTRC^
@^@^D<^@^@^H^LgTRC^@^@^D<^@^@^H^LbTRC^@^@^D<^@^@^H^Ltext^@^@^@^@Copyright (
Otro caso de uso para -v
La opción es encontrar caracteres de control que podrían haberse filtrado en un archivo de texto. Si lo recuerdas, tenemos ese extraño problema anterior con -b
opción que numeraba la sexta línea de entrada, mientras que parecía como si estuviera vacío. Así que investiguemos eso:
$ cat -v felidae.txt
Felidae \Felidae\ n.^M
a natural family of lithe-bodied round-headed fissiped^M
mammals, including the cats; wildcats; lions; leopards;^M
cheetahs; and saber-toothed tigers.^M
^M
Syn: family {Felidae}.^M
[WordNet 1.5]^M
¡Ah ah! Ves esos ^M
¿marcas? Se utilizan para reemplazar el carácter de retorno de carro que de otro modo sería invisible. ¿De dónde vino? Bueno, el dict
El protocolo, como cualquier otro protocolo de Internet, utiliza CRLF como terminador de línea. Así que los descargamos como parte de nuestros archivos de muestra. Puede obtener más información sobre saltos de línea y retornos de carro en el fold
y fmt
artículo. Pero por ahora, explica por qué cat
consideró que la sexta línea no estaba vacía.
-e
:mostrar caracteres invisibles, incluido el final de línea
El -e
la opción funciona como -v
opción, excepto que también agregará un signo de dólar ($
) antes de cada carácter de salto de línea, mostrando así explícitamente el final de las líneas:
$ cat -e felidae.txt
$
Felidae \Felidae\ n.^M$
a natural family of lithe-bodied round-headed fissiped^M$
mammals, including the cats; wildcats; lions; leopards;^M$
cheetahs; and saber-toothed tigers.^M$
^M$
Syn: family {Felidae}.^M$
[WordNet 1.5]^M$
$
-t
:muestra caracteres invisibles, incluidas las pestañas
El -t
la opción funciona como -v
opción, excepto que también mostrará tabulaciones usando el ^I
notación de intercalación (la tabulación se almacena como un byte que contiene el valor 9, y I
en ASCII es 64+9=73):
$ cat -t felidae.txt
Felidae \Felidae\ n.^M
^Ia natural family of lithe-bodied round-headed fissiped^M
^Imammals, including the cats; wildcats; lions; leopards;^M
^Icheetahs; and saber-toothed tigers.^M
^M
^ISyn: family {Felidae}.^M
^I^I [WordNet 1.5]^M
-et
:mostrar todos los caracteres ocultos
Como ya lo mencioné brevemente, si desea mostrar todos los caracteres no imprimibles, incluidas las tabulaciones y los marcadores de fin de línea, deberá usar tanto el -e
y -t
opciones:
$ cat -et felidae.txt
$
Felidae \Felidae\ n.^M$
^Ia natural family of lithe-bodied round-headed fissiped^M$
^Imammals, including the cats; wildcats; lions; leopards;^M$
^Icheetahs; and saber-toothed tigers.^M$
^M$
^ISyn: family {Felidae}.^M$
^I^I [WordNet 1.5]^M$
$
Bonificación:El uso inútil del comando cat en Linux
Ningún artículo sobre el cat
El comando estaría completo sin una mención del antipatrón "Uso inútil del gato".
Ocurre cuando usas cat
con el único propósito de enviar el contenido de un archivo a la entrada estándar de otro comando. Ese uso del cat
El comando se dice "inútil" ya que una simple redirección o un parámetro de nombre de archivo habría hecho el trabajo y lo habría hecho mejor. Pero un ejemplo que vale más que mil palabras:
$ curl -so - dict://dict.org/'d:uuoc:jargon' | sed -Ee '/^151/,/^[.]/!d;/^[.0-9]/s/.*//' > uuoc.txt
$ cat uuoc.txt | less
UUOC
[from the comp.unix.shell group on Usenet] Stands for Useless Use of {cat};
the reference is to the Unix command cat(1), not the feline animal. As
received wisdom on comp.unix.shell observes, ?The purpose of cat is to
concatenate (or ?catenate?) files. If it's only one file, concatenating it
with nothing at all is a waste of time, and costs you a process.?
Nevertheless one sees people doing
cat file | some_command and its args ...
instead of the equivalent and cheaper
<file some_command and its args ...
or (equivalently and more classically)
some_command and its args ... <file
[...]
En el ejemplo anterior, utilicé una canalización para mostrar el contenido de uuoc.txt
archivo con less
localizador:
cat uuoc.txt | less
Entonces, el único propósito del cat
El comando era alimentar la entrada estándar de less
comando con el contenido de uuoc.txt
expediente. Hubiera obtenido el mismo comportamiento usando una redirección de shell:
less < uuoc.txt
De hecho, el less
El comando, como muchos comandos, también acepta un nombre de archivo como argumento. Así que simplemente podría haber escrito eso en su lugar:
less uuoc.txt
Como puede ver, no es necesario cat
aquí. Si menciono el antipatrón “Useless Use of Cat”, es porque, si lo usas públicamente en un foro o en otro lugar, sin duda alguien te lo señalará con el argumento de que crearás un “proceso extra para nada”. ”
Debo admitir que durante mucho tiempo fui bastante desdeñoso con tales comentarios. Después de todo, en nuestro hardware moderno, generar un proceso adicional para una operación única no podría generar tanta sobrecarga.
Pero mientras escribía este artículo, hice un experimento rápido, comparando el tiempo requerido con y sin UUOC mediante una prueba awk
script para procesar 500 MB de datos provenientes de un medio lento.
Para mi sorpresa, la diferencia estaba lejos de ser insignificante:
Sin embargo, la razón no se trata de que se cree un proceso adicional. Pero debido a la lectura/escritura adicional y al cambio de contexto en el que incurre el UUOC (como se puede inferir del tiempo dedicado a ejecutar el código del sistema). De hecho, cuando trabajas en grandes conjuntos de datos, ese cat
extra El comando tiene un costo no despreciable. En cuanto a mí, ¡intentaré estar más atento con eso ahora! ¿Y usted? Si tienes ejemplos del uso inútil del gato, ¡no dudes en compartirlos con nosotros!