Важно понимать, что здесь есть компромисс.
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