README · by ansango
← Volver al libro

Compresión y archivado

Cómo empaquetar archivos con tar, comprimirlos con gzip, bzip2 y compress, y hacer copias bit a bit de dispositivos con dd

~6 min de lectura
Resumen

Cheatsheet para combinar varios archivos en uno solo con tar, reducir su tamaño con gzip, bzip2 o compress, y hacer copias exactas (bit a bit) de discos o particiones con dd, la herramienta más potente y también más peligrosa de este grupo. Incluye el porqué de la compresión con pérdida frente a sin pérdida y una comparativa real de ratio/velocidad entre los tres compresores.

Qué es comprimir, y por qué importa la pérdida

Comprimir es, en esencia, representar la misma información con menos bytes. Existen dos familias completamente distintas, y confundirlas puede arruinar un archivo:

Como hacker o administrador, casi nunca vas a comprimir con pérdida tú mismo: la usarás sobre todo para reconocer con qué se comprimió algo que recibes (una captura, un vídeo de PoC) y saber que, si lo recomprimes, perderás aún más calidad. Para transferir herramientas, exploits o backups, sin pérdida es la única opción razonable.

Empaquetar archivos con tar

tar (tape archive, herencia de cuando los datos se guardaban en cintas magnéticas) combina varios archivos en uno solo, llamado tarball. Es el paso previo casi obligado antes de comprimir o de enviar un conjunto de archivos como una unidad.

tar -cvf paquete.tar archivo1 archivo2 archivo3
El tarball resultante ocupa algo más que la suma de los archivos originales:

tar añade cabeceras y metadatos por cada archivo incluido. Con archivos pequeños ese overhead es perceptible; con archivos grandes se vuelve insignificante.

El overhead con números reales

Empaquetando tres scripts de 22.311, 8.791 y 3.992 bytes (35.094 bytes en total), el tarball resultante ocupa 40.960 bytes: tar ha añadido algo más de 5.000 bytes solo en cabeceras. Con tres archivos de varios megas cada uno, ese mismo overhead de unos pocos KB pasaría totalmente desapercibido — el coste de tar es fijo por archivo incluido, no proporcional a su tamaño.

Ver el contenido sin extraer

tar -tvf paquete.tar

Lista los archivos contenidos en el tarball (con su tamaño y fecha) sin extraerlos, útil para comprobar qué hay dentro antes de descomprimir algo que no controlas.

Extraer un tarball

tar -xvf paquete.tar     # extrae mostrando el detalle de cada archivo
tar -xf paquete.tar      # extrae en silencio, sin listado
Si al extraer ya existe un archivo con el mismo nombre en el directorio de destino,

tar lo sobrescribe sin pedir confirmación. Comprueba el contenido con -tvf antes de extraer sobre un directorio que ya tenga archivos con esos nombres.

Comprimir archivos

Un tarball por sí solo no comprime nada, solo agrupa. Para reducir el tamaño real hay tres utilidades habituales en Linux, cada una con un compromiso distinto entre velocidad y ratio de compresión:

HerramientaExtensiónVelocidadTamaño resultante
compress.tar.ZLa más rápidaEl más grande de los tres
gzip.tar.gz / .tgzIntermediaIntermedio
bzip2.tar.bz2La más lentaEl más pequeño de los tres
Comparativa con el mismo tarball de 40.960 bytes

Comprimiendo el mismo HackersArise.tar de la sección anterior con cada herramienta se obtienen resultados muy distintos:

La diferencia entre compress y bzip2 es de más del doble en tamaño final. Con archivos de texto (scripts, logs, configuración) esta brecha se nota mucho; con archivos ya comprimidos de origen (imágenes, binarios) las tres herramientas convergen porque apenas queda redundancia que exprimir.

gzip

gzip paquete.tar        # genera paquete.tar.gz y borra el .tar original
gunzip paquete.tar.gz    # descomprime y recupera paquete.tar

bzip2

bzip2 paquete.tar        # genera paquete.tar.bz2
bunzip2 paquete.tar.bz2   # descomprime y recupera paquete.tar

compress

compress paquete.tar      # genera paquete.tar.Z
uncompress paquete.tar.Z  # descomprime y recupera paquete.tar

gzip es, con diferencia, el formato más habitual en el mundo Linux (muchos man pages y logs rotados terminan como .gz). Conocer los otros dos sirve sobre todo para reconocer con qué se comprimió un archivo que te llega de fuera y saber qué comando usar para descomprimirlo. gunzip además puede descomprimir archivos .Z generados con compress.

Flujo completo típico

Empaquetar y comprimir en dos pasos es el patrón más común para preparar una copia de seguridad o un envío de archivos.

Empaquetar y comprimir en un solo comando

En la práctica, casi nadie hace tar y luego gzip como dos comandos separados: tar acepta un flag adicional que llama al compresor por ti en el mismo paso, sin generar el .tar intermedio.

tar -czvf backup.tar.gz /home/ansango/proyecto     # tar + gzip en un solo paso (z)
tar -cjvf backup.tar.bz2 /home/ansango/proyecto    # tar + bzip2 en un solo paso (j)
tar -cJvf backup.tar.xz /home/ansango/proyecto     # tar + xz en un solo paso (J, mayúscula)

Y a la inversa, para extraer directamente sin descomprimir en un paso previo:

tar -xzvf backup.tar.gz     # descomprime gzip y extrae en el mismo comando
tar -xjvf backup.tar.bz2    # ídem con bzip2
tar -xJvf backup.tar.xz     # ídem con xz
Aunque no aparezca en el libro (que se centra en

gzip, bzip2 y compress), xz es hoy el formato de referencia cuando el ratio de compresión importa más que la velocidad: comprime bastante mejor que bzip2 a costa de ser todavía más lento, y es el formato habitual para distribuir código fuente de proyectos grandes (kernel de Linux incluido). Si bzip2 te parece lento pero necesitas apurar el tamaño, xz es el siguiente paso lógico.

Copias bit a bit con dd

dd hace algo muy distinto a cp: copia un dispositivo o archivo bit a bit, incluyendo bloques marcados como borrados a nivel de sistema de archivos. Es la herramienta de referencia en análisis forense y en clonado de discos, precisamente porque no respeta la capa lógica del sistema de archivos: copia lo que hay físicamente en el dispositivo, borrado o no.

dd if=/dev/sdb of=/root/copia_flash bs=4096 conv=noerror
Por qué dd y no cp

cp opera a nivel lógico: le pides “copia este archivo” y el sistema de archivos decide qué bloques leer, ignorando cualquier cosa marcada como borrada o libre. dd no sabe nada de archivos ni de sistemas de archivos — copia byte a byte todo lo que hay en el dispositivo de origen, tal cual, sin preguntar qué representa cada bloque. Esa es la razón de que un dd if=/dev/sdb of=copia.img conserve datos que un usuario borró hace tiempo (el espacio quedó marcado como libre, pero el contenido sigue físicamente ahí hasta que algo lo sobrescribe). Es exactamente lo que busca un investigador forense, y exactamente lo que busca un atacante que ha comprometido una máquina y quiere llevarse una copia exacta del disco.

Un ejemplo real del libro, clonando una memoria flash de 7,6 GB:

dd if=/dev/sdb of=/root/flashcopy
# 1257440+0 records in
# 1257440+0 records out
# 7643809280 bytes (7.6 GB) copied, 1220.729 s, 5.2 MB/s

Sin especificar bs, dd usa bloques de 512 bytes por defecto, lo que explica la velocidad modesta (5.2 MB/s). Ajustando el tamaño de bloque al tamaño de sector real del dispositivo se reduce drásticamente el número de operaciones de E/S necesarias:

dd if=/dev/sdb of=/root/flashcopy bs=4096 conv=noerror
Dos variantes útiles que no vienen en el ejemplo básico:

dd no pregunta confirmación y no entiende de “deshacer”. Si intercambias if y of, o simplemente escribes mal el dispositivo de destino (por ejemplo, of=/dev/sda en vez de of=/dev/sdb), puedes sobrescribir tu disco principal en segundos sin ningún aviso. Antes de ejecutar dd, verifica siempre con lsblk o fdisk -l qué dispositivo es cuál — se explica en la siguiente nota.

dd es intencionadamente lento comparado con cp o herramientas de clonado especializadas, porque copia todo el dispositivo byte a byte sin las optimizaciones que aporta conocer la estructura del sistema de archivos. No lo uses para copiar archivos del día a día: resérvalo para clonado de discos completos, forense o recuperación de datos borrados.

Próximos pasos