36

Архивация и компрессия файлов. Часть 2

Многие файлы содержат сколь-нибудь повторяющуюся, лишнюю информацию. Поэтому технически возможно преобразовывать её так, чтобы уменьшить общий размер. Это и есть компрЕссия (compression, "компрЕшэн"), или сжатие, данных.


Сжатие не следует воспринимать как "удаление ненужных частей". Важно, чтобы восстановленный файл имел точно такое же содержимое, что исходный (совпадения размеров файлов - не достаточно).


Есть много алгоритмов компрессии и много форматов сжатых файлов. В UNIX и Linux популярны форматы сжатия Bzip2, Gzip (традиционный), LZMA, XZ. Для примера - те же три файла:


$ cd works

$ cp old/file?.* today/


Компрессор gzip для формата Gzip обычно удаляет файл-операнд; иначе нужна опция -k (от keep):


$ cd today

$ gzip -k file?.*

$ du -k file?.*

100 file1.000

4 file1.000.gz

100 file2.rnd

104 file2.rnd.gz

100 file3.txt

32 file3.txt.gz


Шаблоны имён здесь раскрывает оболочка. Расширение имени здесь добавляется, а не заменяет исходное.

Понятие "степень сжатия" (compression ratio) толкуется по-разному: 1) "какую долю от размера исходного файла составляет размер сжатого файла" либо 2) "какую долю удалось убрать". Обычно выражается в процентах.


Выше видно, что нулевой файл имеет степень сжатия (1) в четыре процента (то есть сжат в 25 раз), случайный файл - 104% (то есть лучше было бы его вовсе не сжимать), текстовый файл - 32% (то есть примерно втрое уменьшился).


Вот вывод компрессором информации об архиве, в том числе степени сжатия в смысле (2):


$ gzip -l file3.txt.gz | column -t

compressed uncompressed ratio uncompressed_name

29806 102400 70.9% file3.txt


В выводе не учтены внутренние вспомогательные данные формата, здесь - около 3 КиБ: 100 - 71 = 29; 32 - 29 = 3.


Нередко алгоритм допускает несколько степеней сжатия. По умолчанию программа обычно выбирает нечто среднее. За более сильное сжатие (меньше размер) приходится платить увеличенными временем упаковки и расходом оперативной памяти. Нередко выигрыш в степени сжатия оказывается незначителен. Скорость распаковки остаётся прежней.


$ rm file{2,3}.*.gz

$ gzip -fkv --best file{2,3}.*

file2.rnd: -0.0% -- replaced with file2.rnd.gz

file3.txt: 70.9% -- replaced with file3.txt.gz

$ du -k file{2,3}.*

100 file2.rnd

104 file2.rnd.gz

100 file3.txt

32 file3.txt.gz


В данном случае - никакой разницы.


Опция -f - принудительное выполнение (от force), то есть здесь - заменить (replace) уже существующий сжатый файл новым. Опция --best - сжать наилучшим доступным алгоритмом (с параметрами, нацеленными на наиболее сильное сжатие).


Можно попробовать другой компрессор/формат, например bzip2 (Bzip2, ".bz2"):


$ bzip2 -k file3.txt

$ du -k file3.*

100 file3.txt

28 file3.txt.bz2

32 file3.txt.gz


Здесь есть небольшой выигрыш: 32 - 28 = 4.


Нет простого способа узнать, насколько сильным будет сжатие. Тексты часто сжимаются со степенью (1) ниже 50%. Хуже всего сжимаются хаотичные (случайные, шум) данные.


Для удобства можно считать, что для файлов средних размеров сжатие уместно, если степень (1) составляет 60% и ниже (то есть сэкономлено 40% места и больше). Если файл большой (1 ГиБ и выше), то даже небольшая экономия при сжатии может быть уместна. Уже сжатый файл обычно бесполезно сжимать ещё раз. Файлы размером ниже 3 КиБ сжимать тоже бесполезно.


Для "декомпрессии" (распаковки, извлечения оригинала) сжатого файла часто есть не только опция компрессора, но и отдельная программа-распаковщик. Или сам компрессор может быть запущен под другим именем файла (например, с жёсткой ссылкой) для распаковки - это зависит от программиста.


$ gzip -d -kf file2.rnd.gz

$ gunzip -kf file2.rnd.gz


Здесь или опция -d, или программа gunzip. Опции -k, -f - с прежним смыслом. Аналогично с BZip2:


$ bzip2 -d -kf file3.txt.bz2

$ bunzip2 -kf file3.txt.bz2

$ diff -qs /bin/bunzip2 /bin/bzip2

Файлы /bin/bunzip2 и /bin/bzip2 идентичны


Документация: man-страницы.


Чтобы задействовать содержимое оригинального (несжатого файла), обычно нужно явным способом распаковать сжатый. На это тратится процессорное время; в мобильном компьютере может быть повышенный расход заряда аккумулятора. Кроме того, степень сжатия непредсказуема или даже (1) выше 100%, поэтому при массовых правках файлов свободное место на диске может внезапно закончиться.


Чтобы задействовать содержимое оригинального (несжатого файла), обычно нужно явным способом распаковать сжатый. На это тратится процессорное время; в мобильном компьютере может быть повышенный расход заряда аккумулятора. Кроме того, степень сжатия непредсказуема или даже (1) выше 100%, поэтому при массовых правках файлов свободное место на диске может внезапно закончиться.


Есть несколько форматов файловых систем, где файлы сжимаются/распаковываются автоматически (говорят: "на лету" (on-the-fly) или "прозрачная (transparent) распаковка").


Есть аналоги привычных утилит с именами, начинающимися на bz (для BZip2), xz или z (GZip): bzcat, bzless, bzgrep и другие. Делают то же, что оригиналы, но со сжатыми файлами.


Midnight Commander, подобные ему двухпанельные диспетчеры файлов, некоторые другие диспетчеры - могут открывать/распаковывать архивы/сжатые файлы. Иногда есть возможность имитировать монтирование архива как каталога (только на чтение, иногда ещё и на запись). В таких случаях программе может понадобиться предварительно распаковать файлы во временный каталог (обычно куда-то в /tmp/). Это заметно как зависание программы при работе с большим (несколько десятков МиБ и выше) архивом.


В UNIX и Linux компрессия традиционно является операцией над одиночным файлом. То есть для компрессии каталога с содержимым - нужно сначала создать архив, а потом его сжимать (либо, реже, - сжать каждый файл, а потом заархивировать всё).


Архиватор tar может задействовать какой-либо компрессор, если тот воспринимает просто имя файла как сигнал к сжатию либо воспринимает опцию -d как сигнал к распаковке (декомпрессии). Опции tar для внешних компрессоров: -z для gzip, -j для bzip2, -J для xz. Для остальных компрессоров - опция -I (заглавная i, после которой указать имя программы). Примеры:


# Архив tar внутри сжатого файла Gzip одной командой.

$ tar -cvz -f archive.tar.gz "old"

old/

old/file3.txt

old/file1.000

old/file2.rnd

$ du -s archive.tar.gz

136 archive.tar.gz

# Вывод сокращён.

$ file archive.tar.gz

archive.tar.gz: gzip compressed data


# Архив tar внутри сжатого файла Bzip2 одной командой.

$ tar -cj -f archive.tar.bz2 "old"

$ du -s archive.tar.bz2

132 archive.tar.bz2

$ file archive.tar.bz2

archive.tar.bz2: bzip2 compressed data, block size = 900k


# Архив tar внутри сжатого файла LZMA одной командой.

$ tar -c -I lzma -f archive.tar.lzma "old"

$ du -s archive.tar.lzma

128 archive.tar.lzma

$ file archive.tar.lzma

archive.tar.lzma: LZMA compressed data, streamed


Вместо множественных расширений вида ".tar.gz" могут попадаться одиночные: ".tgz", ".tbz", ".txz" и другие - по традиции или при необходимости соблюдать ограничения на длину имени. Устаревший компрессор - compress; расширение ".Z"; в tar есть опция -Z.


# Примеры распаковки сжатых архивов одной командой:

$ rm -r old/

$ tar -xj -f archive.tar.bz2

# Или:

$ tar -x -I lzma -f archive.tar.lzma


Чтобы изменить содержимое сжатого архива, программе приходится его предварительно распаковывать, а после внесения изменений - заново упаковывать обратно. Это затраты времени, оперативной памяти и, возможно, пространства на диске для временного хранения. Может оказаться удобнее - упаковать файлы в поддереве по отдельности, не создавая архива. У gzip/gunzip есть опция -r (от recursive). Для других программ можно задействовать find (и, если нужно, xargs).


В семействе Windows привыкли воспринимать архивацию и компрессию как единую, неделимую операцию. Часто говорят "заархивировать" в смысле "получить сжатый архив"; "разархивировать" - "выполнить и декомпрессию, и извлечение из архива". Или: "упаковать" и "распаковать" файлы. И сжатые файлы называют "архивами". Для большинства пользователей важно именно сжатие данных, а архивация подразумевается сама собой.


Популярные в Windows форматы сжатых файлов с возможностью хранения файлового поддерева (архива): ZIP, RAR. Соответственно программы: для командной строки - zip.exe, rar.exe; для GUI - WinZip, WinRAR. Диспетчер файлов системы Windows - Проводник (Explorer) может смонтировать архив ZIP как подкаталог там, где находится сам файл архива. Есть и другие программы, в том числе поддерживающие много форматов, например: 7-Zip, PeaZip (и вышеуказанные WinZip, WinRAR).


Набор программ p7zip (в том числе 7z, 7za) является вариантом 7-Zip для командной строки UNIX и Linux. Формат 7z может давать более сильное сжатие, чем Gzip и Bzip2.


В Linux может быть проблема с форматом ZIP для файловых имён, содержащих не-латиницу. У ZIP есть свой внутренний формат хранения имён. Если создать архив в Windows, а потом попытаться распаковать в Linux, имена превратятся в наборы кракозябров. В последнее время дистрибутивы обычно поставляют исправленные программы unzip и zip. Или придётся пробовать перекодировать имена программой iconv или convmv.


Возможные (ненадёжно) варианты перекодировки имени (предполагаемый в примере файл сохранил расширение ".pdf" на латинице, поэтому файл можно как-то задействовать через шаблон оболочки):


$ N=$(ls *.pdf | iconv -f cp1252 -t cp850 | iconv -f cp866)

# Или другой вариант:

$ N=$(ls *.pdf | iconv -t iso8859-1 | iconv -f cp866)


# После каждого варианта просмотреть

# содержимое переменной N для перекодированного имени.

$ echo $N

# И если имя выглядит разумно, то:

$ mv *.pdf "$N"

$ unset N


Программы для Windows часто поставляются в виде особых архивов, в том числе формата Microsoft Cabinet (".cab"). Такие архивы по лицензионным соглашениям запрещено распаковывать вручную. Для Linux есть программа cabextract.


Иногда в России встречаются старые форматы архивов с внутренней компрессией: ARJ, HA, LHA и другие. Для Linux могут найтись программы: arj, ha, unar. Иначе может понадобиться устанавливать FreeDOS/Wine или иную среду выполнения DOS/Windows-программ, а потом искать соответствующие декомпрессоры.


В Windows нередко создают "самораспаковывающиеся" (self-extracting) архивы: это программа-распаковщик, к которой присоединён собственно архив. Как и обычная программа для Windows, имеют расширение ".exe". Предназначены для пользователей, у которых нет своей копии распаковщика. Иногда такой архив можно распаковать и в Linux (зависит от формата архива и наличия программ, например 7-zip). Нежелательны к применению, потому что могут содержать программы-вирусы. Не следует запускать напрямую, а лучше - открыть отдельным распаковщиком. В Linux иногда делают сценарии оболочки, состоящие из команды на распаковку и присоединённого к сценарию архива; программы: makeself, shar (sharutils).


В некоторых форматах архивов и/или сжатых файлов предусмотрено шифрование с паролем: 7z, RAR, ZIP и другие.


Компрессия данных может встретиться и на системном уровне. Например, в некоторых файловых системах нулевые фрагменты (пустые блоки) внутри файлов не хранятся и не копируются (это называется "разреженные файлы", sparse files).


Программы для GUI: Archive Manager (File Roller) для GNOME, Ark для KDE, Engrampa для MATE, PeaZip, Xarchiver. Они отображают содержимое архивов, подобно тому как диспетчеры файлов отображают содержимое каталогов; предоставляют меню команд создания/распаковки архивов. Но сами не содержат программного кода архиваторов/компрессоров, поэтому требуют установки библиотек (libarchive, liblzma, unrar и других) и самих архиваторов/компрессоров для командной строки.


В файлах мультимедиа (изображения, звук, видео) часто применяют алгоритмы "несимметричного" сжатия, то есть с частичной потерей информации. Это позволяет сжать данные ещё сильнее (в десятки или больше раз). Некоторые потери в деталях изображений или в звуковых волнах уместны, если средний человек эти оттенки/детали/шумы и прочее не различает. Такие алгоритмы обычно имеют широкий набор настроек, поэтому нужно следить за тем, чтобы качество мультимедиа не стало плохим, явно заметным.

GNU/Linux

1.2K пост15.6K подписчика

Правила сообщества

Все дистрибутивы хороши.

Будьте людьми.