Es importante entender que hay una compensación aquí.
tar
significa archivador de cinta . En una cinta, la mayoría de las veces se lee y escribe secuencialmente. Las cintas rara vez se usan hoy en día, pero tar
todavía se usan por su capacidad de leer y escribir sus datos como una secuencia.
Tu puedes hacer:
tar cf - files | gzip | ssh host 'cd dest && gunzip | tar xf -'
No se puede hacer eso con zip
o similar.
Ni siquiera puede enumerar el contenido de un zip
archivo sin almacenarlo localmente en un archivo de búsqueda primero. Piensa como:
curl -s https://github.com/dwp-forge/columns/archive/v.2016-02-27.zip | unzip -l /dev/stdin
no funciona
Para lograr esa lectura rápida del contenido, zip
o similar, es necesario construir un índice. Ese índice se puede almacenar al principio del archivo (en cuyo caso solo se puede escribir en archivos normales, no en secuencias), o al final, lo que significa que el archivador debe recordar a todos los miembros del archivo antes de imprimirlo al final y significa que un archivo truncado puede no ser recuperable.
Eso también significa que los miembros del archivo deben comprimirse individualmente, lo que significa una relación de compresión mucho menor, especialmente si hay muchos archivos pequeños.
Otro inconveniente con formatos como zip
es que el archivo está vinculado a la compresión, no puede elegir el algoritmo de compresión. Vea cómo los tar
archivos solían estar comprimidos con compress
( tar.Z
), luego con gzip
, luego bzip2
, a xz
medida que se creaban nuevos algoritmos de compresión más eficaces. Lo mismo ocurre con el cifrado. ¿Quién confiaría en zip
el cifrado hoy en día?
Ahora, el problema con los tar.gz
archivos no es que necesites descomprimirlos. La descompresión a menudo es más rápida que leer un disco (probablemente encontrará que enumerar el contenido de un archivo tgz grande es más rápido que enumerar el mismo sin comprimir cuando no está en la memoria caché), pero que necesita leer todo el archivo.
No poder leer el índice rápidamente no es realmente un problema. Si prevé la necesidad de leer el contenido de la tabla de un archivo a menudo, puede almacenar esa lista en un archivo separado. Por ejemplo, en el momento de la creación, puede hacer:
tar cvvf - dir 2> file.tar.xz.list | xz > file.tar.xz
Un problema mayor de la OMI es el hecho de que, debido al aspecto secuencial del archivo, no puede extraer archivos individuales sin leer toda la sección inicial del archivo que lo conduce. IOW, no puedes hacer lecturas aleatorias dentro del archivo.
Ahora, para archivos buscables, no tiene por qué ser así.
Si comprime su tar
archivo comprimido gzip
, que lo comprime como un todo, el algoritmo de compresión utiliza datos vistos al principio para comprimir, por lo que debe comenzar desde el principio para descomprimir.
Pero el xz
formato se puede configurar para comprimir datos en fragmentos individuales separados (lo suficientemente grande como para que la compresión sea eficiente), eso significa que, siempre y cuando mantenga un índice al final de esos fragmentos comprimidos, para archivos buscables, accederá a datos sin comprimir al azar (al menos en fragmentos).
pixz
(paralelo xz
) usa esa capacidad al comprimir tar
archivos para agregar también un índice del inicio de cada miembro del archivo al final del xz
archivo.
Por lo tanto, para archivos buscables, no solo puede obtener una lista del contenido del archivo tar instantáneamente (sin metadatos) si se han comprimido con pixz
:
pixz -l file.tar.xz
Pero también puede extraer elementos individuales sin tener que leer todo el archivo:
pixz -x archive/member.txt < file.tar.xz | tar xpf -
Ahora, por qué las cosas como 7z
o zip
raramente se usan en Unix es principalmente porque no pueden archivar archivos de Unix. Han sido diseñados para otros sistemas operativos. No puede hacer una copia de seguridad fiel de los datos con esos. No pueden almacenar metadatos como el propietario (id y nombre), permiso, no pueden almacenar enlaces simbólicos, dispositivos, quince ..., no pueden almacenar información sobre enlaces duros y otra información de metadatos como atributos extendidos o ACL.
Algunos de ellos ni siquiera pueden almacenar miembros con nombres arbitrarios (algunos se ahogarán con la barra diagonal inversa o la nueva línea o los dos puntos, o los nombres de archivo no ASCII) ( tar
aunque algunos formatos también tienen limitaciones).
¡Nunca descomprima un archivo tgz / tar.xz en el disco!
En caso de que no es obvio, uno no utiliza tgz
o tar.bz2
, tar.xz
... archivo como:
unxz file.tar.xz
tar tvf file.tar
xz file.tar
Si tienes un .tar
archivo sin comprimir en tu sistema de archivos, es que has hecho algo mal.
El punto principal de esos xz
/ bzip2
/ gzip
ser compresores de flujo es que se pueden usar sobre la marcha, en tuberías como en
unxz < file.tar.xz | tar tvf -
Aunque las tar
implementaciones modernas saben cómo invocar unxz
/ gunzip
/ bzip2
por sí mismas, entonces:
tar tvf file.tar.xz
generalmente también funcionaría (y nuevamente descomprimiría los datos sobre la marcha y no almacenaría la versión descomprimida del archivo en el disco).
Ejemplo
Aquí hay un árbol de fuentes del kernel de Linux comprimido con varios formatos.
$ ls --block-size=1 -sS1
666210304 linux-4.6.tar
173592576 linux-4.6.zip
97038336 linux-4.6.7z
89468928 linux-4.6.tar.xz
Primero, como se señaló anteriormente, los 7z y los zip son ligeramente diferentes porque no pueden almacenar los pocos enlaces simbólicos allí y les falta la mayoría de los metadatos.
Ahora, algunos tiempos para enumerar el contenido después de haber vaciado los cachés del sistema:
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ time tar tvf linux-4.6.tar > /dev/null
tar tvf linux-4.6.tar > /dev/null 0.56s user 0.47s system 13% cpu 7.428 total
$ time tar tvf linux-4.6.tar.xz > /dev/null
tar tvf linux-4.6.tar.xz > /dev/null 8.10s user 0.52s system 118% cpu 7.297 total
$ time unzip -v linux-4.6.zip > /dev/null
unzip -v linux-4.6.zip > /dev/null 0.16s user 0.08s system 86% cpu 0.282 total
$ time 7z l linux-4.6.7z > /dev/null
7z l linux-4.6.7z > /dev/null 0.51s user 0.15s system 89% cpu 0.739 total
Notarás que enumerar el tar.xz
archivo es más rápido que el .tar
de esta PC de 7 años, ya que leer esos megabytes adicionales del disco lleva más tiempo que leer y descomprimir el archivo más pequeño.
Entonces, OK, enumerar los archivos con 7z o zip es más rápido, pero eso no es un problema, como dije, se soluciona fácilmente almacenando la lista de archivos junto al archivo:
$ tar tvf linux-4.6.tar.xz | xz > linux-4.6.tar.xz.list.xz
$ ls --block-size=1 -sS1 linux-4.6.tar.xz.list.xz
434176 linux-4.6.tar.xz.list.xz
$ time xzcat linux-4.6.tar.xz.list.xz > /dev/null
xzcat linux-4.6.tar.xz.list.xz > /dev/null 0.05s user 0.00s system 99% cpu 0.051 total
Incluso más rápido que 7z o zip incluso después de soltar cachés. También notará que el tamaño acumulativo del archivo y su índice es aún más pequeño que los archivos zip o 7z.
O use el pixz
formato indexado:
$ xzcat linux-4.6.tar.xz | pixz -9 > linux-4.6.tar.pixz
$ ls --block-size=1 -sS1 linux-4.6.tar.pixz
89841664 linux-4.6.tar.pixz
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ time pixz -l linux-4.6.tar.pixz > /dev/null
pixz -l linux-4.6.tar.pixz > /dev/null 0.04s user 0.01s system 57% cpu 0.087 total
Ahora, para extraer elementos individuales del archivo, el peor de los casos para un archivo tar es acceder al último elemento:
$ xzcat linux-4.6.tar.xz.list.xz|tail -1
-rw-rw-r-- root/root 5976 2016-05-15 23:43 linux-4.6/virt/lib/irqbypass.c
$ time tar xOf linux-4.6.tar.xz linux-4.6/virt/lib/irqbypass.c | wc
257 638 5976
tar xOf linux-4.6.tar.xz linux-4.6/virt/lib/irqbypass.c 7.27s user 1.13s system 115% cpu 7.279 total
wc 0.00s user 0.00s system 0% cpu 7.279 total
Eso es bastante malo ya que necesita leer (y descomprimir) todo el archivo. Comparar con:
$ time unzip -p linux-4.6.zip linux-4.6/virt/lib/irqbypass.c | wc
257 638 5976
unzip -p linux-4.6.zip linux-4.6/virt/lib/irqbypass.c 0.02s user 0.01s system 19% cpu 0.119 total
wc 0.00s user 0.00s system 1% cpu 0.119 total
Parece que mi versión de 7z no puede hacer acceso aleatorio, por lo que parece ser aún peor que tar.xz
:
$ time 7z e -so linux-4.6.7z linux-4.6/virt/lib/irqbypass.c 2> /dev/null | wc
257 638 5976
7z e -so linux-4.6.7z linux-4.6/virt/lib/irqbypass.c 2> /dev/null 7.28s user 0.12s system 89% cpu 8.300 total
wc 0.00s user 0.00s system 0% cpu 8.299 total
Ahora, ya que tenemos nuestro pixz
generado desde antes:
$ time pixz < linux-4.6.tar.pixz -x linux-4.6/virt/lib/irqbypass.c | tar xOf - | wc
257 638 5976
pixz -x linux-4.6/virt/lib/irqbypass.c < linux-4.6.tar.pixz 1.37s user 0.06s system 84% cpu 1.687 total
tar xOf - 0.00s user 0.01s system 0% cpu 1.693 total
wc 0.00s user 0.00s system 0% cpu 1.688 total
Es más rápido pero aún relativamente lento porque el archivo contiene algunos bloques grandes:
$ pixz -tl linux-4.6.tar.pixz
17648865 / 134217728
15407945 / 134217728
18275381 / 134217728
19674475 / 134217728
18493914 / 129333248
336945 / 2958887
Por lo tanto, pixz
aún necesita leer y descomprimir una gran cantidad de datos (hasta a) ~ 19 MB.
Podemos hacer que el acceso aleatorio sea más rápido al hacer que los archivos sean bloques más pequeños (y sacrificar un poco de espacio en disco):
$ pixz -f0.25 -9 < linux-4.6.tar > linux-4.6.tar.pixz2
$ ls --block-size=1 -sS1 linux-4.6.tar.pixz2
93745152 linux-4.6.tar.pixz2
$ time pixz < linux-4.6.tar.pixz2 -x linux-4.6/virt/lib/irqbypass.c | tar xOf - | wc
257 638 5976
pixz -x linux-4.6/virt/lib/irqbypass.c < linux-4.6.tar.pixz2 0.17s user 0.02s system 98% cpu 0.189 total
tar xOf - 0.00s user 0.00s system 1% cpu 0.188 total
wc 0.00s user 0.00s system 0% cpu 0.187 total