Важно понимать, что здесь есть компромисс.
tar
означает ленточный архиватор . На ленте вы делаете в основном последовательное чтение и запись. В настоящее время ленты используются редко, но tar
все еще используются для его способности читать и записывать свои данные в виде потока.
Ты можешь сделать:
tar cf - files | gzip | ssh host 'cd dest && gunzip | tar xf -'
Вы не можете сделать это с zip
или тому подобное.
Вы даже не можете перечислить содержимое zip
архива, не сохранив его локально в доступном для поиска файле. Думает как:
curl -s https://github.com/dwp-forge/columns/archive/v.2016-02-27.zip | unzip -l /dev/stdin
не сработает
Для быстрого чтения содержимого zip
и т. П. Необходимо создать индекс. Этот индекс может быть сохранен в начале файла (в этом случае он может быть записан только в обычные файлы, а не в потоки) или в конце, что означает, что архиватор должен запомнить все элементы архива перед его печатью в конце и означает, что усеченный архив не может быть восстановлен.
Это также означает, что члены архива должны быть сжаты по отдельности, что означает гораздо более низкую степень сжатия, особенно если много маленьких файлов.
Еще один недостаток таких форматов, как zip
то, что архивирование связано со сжатием, вы не можете выбрать алгоритм сжатия. Посмотрите, как tar
архивы раньше сжимались с помощью compress
( tar.Z
), затем с gzip
, затем bzip2
, тогда, xz
когда были разработаны новые более производительные алгоритмы сжатия. То же самое касается шифрования. Кто будет доверять zip
шифрованию в наше время?
Теперь проблема с tar.gz
архивами заключается не в том, что вам нужно их распаковывать. Распаковка часто происходит быстрее, чем чтение с диска (вы, вероятно, обнаружите, что распечатка содержимого большого архива tgz быстрее, чем распечатка того же распакованного, когда он не кэширован в памяти), но вам нужно прочитать весь архив.
Неспособность быстро прочитать индекс - не проблема. Если вы предвидите необходимость часто читать содержимое таблицы архива, вы можете просто сохранить этот список в отдельном файле. Например, во время создания вы можете сделать:
tar cvvf - dir 2> file.tar.xz.list | xz > file.tar.xz
Более серьезной проблемой IMO является тот факт, что из-за последовательного аспекта архива вы не можете извлечь отдельные файлы, не прочитав весь начальный раздел архива, который ведет к нему. IOW, вы не можете делать случайные чтения в архиве.
Теперь, для поиска файлов, это не должно быть так.
Если вы сжимаете свой tar
архив gzip
, который сжимает его как единое целое, алгоритм сжатия использует данные, которые были видны в начале, чтобы сжимать, поэтому вы должны начать с начала, чтобы распаковать.
Но xz
формат может быть сконфигурирован для сжатия данных в отдельных отдельных чанках (достаточно больших, чтобы сжатие было эффективным), это означает, что до тех пор, пока вы сохраняете индекс в конце этих сжатых чанков, для доступных для поиска файлов вы получаете доступ к несжатые данные случайным образом (по крайней мере, кусками).
pixz
(параллельно xz
) использует эту возможность при сжатии tar
архивов, чтобы также добавить индекс начала каждого элемента архива в конце xz
файла.
Таким образом, для доступных для поиска файлов вы можете не только получить список содержимого архива tar мгновенно (но без метаданных), если они были сжаты с помощью pixz
:
pixz -l file.tar.xz
Но вы также можете извлечь отдельные элементы, не читая весь архив:
pixz -x archive/member.txt < file.tar.xz | tar xpf -
Теперь, почему такие вещи, как 7z
или zip
редко используются в Unix, в основном потому, что они не могут архивировать файлы Unix. Они были разработаны для других операционных систем. Вы не можете сделать точную резервную копию данных, используя их. Они не могут хранить метаданные, такие как владелец (идентификатор и имя), разрешение, они не могут хранить символические ссылки, устройства, fifos ..., они не могут хранить информацию о жестких ссылках и другую информацию метаданных, такую как расширенные атрибуты или ACL.
Некоторые из них не могут даже хранить элементы с произвольными именами (некоторые будут задыхаться от обратной косой черты, или новой строки, или двоеточия, или имен файлов, отличных от ascii) ( tar
хотя некоторые форматы также имеют ограничения).
Никогда не распаковывайте файл tgz / tar.xz на диск!
В случае , если это не очевидно, один не использовать tgz
или tar.bz2
, tar.xz
... архив как:
unxz file.tar.xz
tar tvf file.tar
xz file.tar
Если .tar
в вашей файловой системе лежит несжатый файл, значит, вы сделали что-то не так.
Весь смысл этих xz
/ bzip2
/ gzip
потоковых компрессоров заключается в том, что они могут использоваться на лету, в трубопроводах, как в
unxz < file.tar.xz | tar tvf -
Хотя современные tar
реализации знают, как вызыватьunxz
/ gunzip
/ bzip2
самостоятельно, поэтому:
tar tvf file.tar.xz
обычно также работает (и снова распаковывает данные на лету, а не сохраняет несжатую версию архива на диске).
пример
Вот дерево исходного кода ядра Linux, сжатое в различных форматах.
$ 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
Во-первых, как отмечалось выше, 7z и zip немного отличаются, потому что они не могут хранить там несколько символических ссылок и пропускают большую часть метаданных.
Теперь несколько моментов для отображения содержимого после очистки системных кэшей:
$ 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
Вы заметите, что листинг tar.xz
файла быстрее, чем.tar
даже на этом 7-летнем ПК, поскольку чтение этих дополнительных мегабайт с диска занимает больше времени, чем чтение и распаковка меньшего файла.
Тогда хорошо, перечисление архивов с помощью 7z или zip происходит быстрее, но это не проблема, поскольку, как я уже сказал, это легко обойти, сохранив список файлов рядом с архивом:
$ 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
Даже быстрее чем 7z или zip даже после сброса кешей. Вы также заметите, что совокупный размер архива и его индекс по-прежнему меньше, чем у архивов zip или 7z.
Или используйте pixz
индексированный формат:
$ 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
Теперь, чтобы извлечь отдельные элементы архива, наихудший сценарий для архива tar - это доступ к последнему элементу:
$ 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
Это довольно плохо, так как нужно читать (и распаковывать) весь архив. Сравнить с:
$ 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
Моя версия 7z не может выполнять произвольный доступ, поэтому она выглядит еще хуже, чем 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
Теперь, так как мы создали наш pixz
ранее:
$ 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
Это быстрее, но все еще относительно медленно, потому что архив содержит несколько больших блоков:
$ pixz -tl linux-4.6.tar.pixz
17648865 / 134217728
15407945 / 134217728
18275381 / 134217728
19674475 / 134217728
18493914 / 129333248
336945 / 2958887
Поэтому по- pixz
прежнему необходимо читать и распаковывать (до) ~ 19 МБ большой кусок данных.
Мы можем сделать произвольный доступ быстрее, сделав архивы меньшими блоками (и пожертвовав немного дискового пространства):
$ 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