É importante entender que há uma troca aqui.
tar
significa arquivador de fitas . Em uma fita, você faz principalmente leitura e escrita seqüencial. Atualmente, as fitas raramente são usadas, mas tar
ainda são usadas por sua capacidade de ler e gravar seus dados como um fluxo.
Você pode fazer:
tar cf - files | gzip | ssh host 'cd dest && gunzip | tar xf -'
Você não pode fazer isso com zip
ou algo parecido.
Você não pode nem listar o conteúdo de um zip
arquivo morto sem armazená-lo localmente em um arquivo procurável primeiro. Pensa como:
curl -s https://github.com/dwp-forge/columns/archive/v.2016-02-27.zip | unzip -l /dev/stdin
não vai funcionar.
Para conseguir essa leitura rápida do conteúdo, zip
ou algo semelhante, é necessário criar um índice. Esse índice pode ser armazenado no início do arquivo (nesse caso, só pode ser gravado em arquivos regulares, não em fluxos) ou no final, o que significa que o arquivador precisa lembrar de todos os membros do arquivo antes de imprimi-lo no final e significa que um arquivo truncado pode não ser recuperável.
Isso também significa que os membros do arquivo precisam ser compactados individualmente, o que significa uma taxa de compactação muito menor, especialmente se houver muitos arquivos pequenos.
Outra desvantagem com formatos como zip
é que o arquivamento está vinculado à compactação, não é possível escolher o algoritmo de compactação. Veja como os tar
arquivos costumavam ser compactados com compress
( tar.Z
), depois com gzip
, então bzip2
, então, à xz
medida que novos algoritmos de compactação com melhor desempenho eram criados. O mesmo vale para criptografia. Quem confiaria zip
na criptografia de hoje em dia?
Agora, o problema com os tar.gz
arquivos não é tanto que você precisa descompactá-los. A descompactação geralmente é mais rápida do que a leitura de um disco (você provavelmente descobrirá que listar o conteúdo de um arquivo tgz grande é mais rápido que listar o mesmo descompactado quando não estiver armazenado em cache na memória), mas é necessário ler o arquivo inteiro.
Não conseguir ler o índice rapidamente não é realmente um problema. Se você prever a necessidade de ler o conteúdo da tabela de um arquivo morto com frequência, poderá simplesmente armazenar essa lista em um arquivo separado. Por exemplo, no momento da criação, você pode:
tar cvvf - dir 2> file.tar.xz.list | xz > file.tar.xz
Um problema maior da IMO é o fato de que, devido ao aspecto seqüencial do arquivo, você não pode extrair arquivos individuais sem ler toda a seção inicial do arquivo que leva a ele. IOW, você não pode fazer leituras aleatórias dentro do arquivo morto.
Agora, para arquivos pesquisáveis, não precisa ser assim.
Se você compactar seu tar
arquivo compactado gzip
, que o compacta como um todo, o algoritmo de compactação usa os dados vistos no início para compactar, portanto, é necessário começar do início para descompactar.
Mas o xz
formato pode ser configurado para compactar dados em blocos individuais separados (grandes o suficiente para que a compactação seja eficiente), isso significa que, desde que você mantenha um índice no final desses blocos compactados, para arquivos procuráveis, acesse o dados não compactados aleatoriamente (pelo menos em partes).
pixz
(paralelo xz
) usa esse recurso ao compactar tar
arquivos para adicionar também um índice do início de cada membro do arquivo ao final do xz
arquivo.
Portanto, para arquivos buscáveis, você não apenas pode obter uma lista do conteúdo do arquivo tar instantaneamente (sem metadados) se eles foram compactados com pixz
:
pixz -l file.tar.xz
Mas você também pode extrair elementos individuais sem precisar ler o arquivo inteiro:
pixz -x archive/member.txt < file.tar.xz | tar xpf -
Agora, o motivo pelo qual coisas como 7z
ou zip
raramente são usadas no Unix é principalmente porque elas não podem arquivar arquivos Unix. Eles foram projetados para outros sistemas operacionais. Você não pode fazer um backup fiel dos dados usando esses. Eles não podem armazenar metadados como proprietário (ID e nome), permissão, eles não podem armazenar links simbólicos, dispositivos, fifos ..., eles não podem armazenar informações sobre links físicos e outras informações de metadados, como atributos estendidos ou ACLs.
Alguns deles nem sequer podem armazenar membros com nomes arbitrários (alguns se engasgam com barra invertida ou nova linha ou dois pontos, ou nomes de arquivos não-ascii) (alguns tar
formatos também têm limitações).
Nunca descompacte um arquivo tgz / tar.xz no disco!
No caso não é óbvio, não se usar um tgz
ou tar.bz2
, tar.xz
... arquivar como:
unxz file.tar.xz
tar tvf file.tar
xz file.tar
Se você tem um .tar
arquivo descompactado no seu sistema de arquivos, é que você fez algo errado.
O ponto de toda aqueles xz
/ bzip2
/ gzip
sendo compressores de transmissão é que eles podem ser usados na mosca, em oleodutos como em
unxz < file.tar.xz | tar tvf -
Embora as tar
implementações modernas saibam chamar unxz
/ gunzip
/ bzip2
por si mesmas, então:
tar tvf file.tar.xz
geralmente também funcionaria (e descompactaria os dados rapidamente e não armazenaria a versão não compactada do arquivo no disco).
Exemplo
Aqui está uma árvore de fontes do kernel Linux compactada com vários 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
Primeiro, como observado acima, os 7z e zip são um pouco diferentes porque não podem armazenar os poucos links simbólicos e faltam a maioria dos metadados.
Agora, alguns intervalos para listar o conteúdo depois de liberar os caches do 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
Você notará que a listagem do tar.xz
arquivo é mais rápida que a do .tar
PC de 7 anos, pois a leitura desses megabytes extras do disco leva mais tempo do que a leitura e descompactação do arquivo menor.
Então, OK, listar os arquivos com 7z ou zip é mais rápido, mas isso não é um problema, como eu disse, é fácil contornar o armazenamento da lista de arquivos ao lado do arquivo:
$ 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
Ainda mais rápido que 7z ou zip, mesmo após a remoção de caches. Você também notará que o tamanho cumulativo do arquivo morto e seu índice ainda são menores que os arquivos zip ou 7z.
Ou use o 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
Agora, para extrair elementos individuais do arquivo, o pior cenário para um arquivo tar é ao acessar o ú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
Isso é muito ruim, pois ele precisa ler (e descompactar) todo o arquivo. Compare com:
$ 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
Minha versão do 7z parece não ser capaz de acessar aleatoriamente, então parece ser ainda pior do 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
Agora, já que pixz
geramos um dos anteriores:
$ 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
É mais rápido, mas ainda relativamente lento, porque o arquivo contém alguns blocos grandes:
$ pixz -tl linux-4.6.tar.pixz
17648865 / 134217728
15407945 / 134217728
18275381 / 134217728
19674475 / 134217728
18493914 / 129333248
336945 / 2958887
Portanto, pixz
ainda é necessário ler e descompactar uma grande quantidade de dados (de até) ~ 19 MB.
Podemos tornar o acesso aleatório mais rápido, tornando os arquivos com blocos menores (e sacrificando um pouco de espaço em 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