Как стать автором
Обновить

Ещё одна заметка про tar

Уровень сложностиПростой
Время на прочтение8 мин
Количество просмотров2.4K

Ко мне как-то обратился коллега с вопросом: «А ты запомнил команду для подготовки архива .tar.gz?» И я такой на автомате: «tar zcf имя.tar.gz ...» А он мне в ответ: «Нет, ты не понял. Ты эту команду запомнил? Мне приходится «гуглить» каждый раз, когда требуется сделать архив.» Ах, вот в чём дело. Действительно, команду я запомнил и уже давольно давно.

Если уважаемый читать хочет узнать немного больше, то предлагаю продолжить чтение. Но хочу предупредить, что ничего ранее неизвестного и сокровенного в заметке про tar не стоит ждать (почти). Всё ещё хочется узнать подробности?

TL; DR: На самом деле самые необходимые опции команды tar заполнить довольно просто, особенно если знать систему, по которой их обрабатывает программа: ccreate, x — extract, ffile name, z — gzip/ungzip. Сначала лучше писать параметры — z, потом действие — c или x, в конце имя файла — f (и имя файла). Для распаковки z указывать не требуется, т.к. современные версии tar умеют определять тип сжатия самостоятельно.

Историческая справка

«Позволю себе — просто 30 секунд или одну минуту — маленькую историческую справку дать. Вы не против?»

Краткая историческая справка по tar.
Краткая историческая справка по tar.

Программа tar была разработана Bell Labs и вошла в Version 7 UNIX в 1979 году. Ого! Вот это старичок! На самом деле программа появилась не на пустом месте, а заменила программу tp из Version 4 UNIX (которая, в свою очередь заменила программу tap из первой редакции UNIX). Задача tar сохранить файлы и каталоги, а также их атрибуты в одном архиве для последующей записи на носители, на которых отсутствует файловая система. В стародавние времена это был ленточный накопитель. Сейчас, впрочем, тоже. Отсюда и названия программ – tap (tape, лента), tp, tar (tape archive, ленточный архив). Хотя в общем-то никто не запретит записать tar-архив вместо UDF образа на DVD-R.

Стоит отметить, что у tar есть конкурент — cpio. Программа изначально появилась в Programmer's Workbench (PWB/UNIX) в 1977 году, а затем вошла в UNIX System III и UNIX System V. Поскольку функционально cpio — это аналог tar, то мы имеем дело с классическим холиваром (holy war).

Салах ад-Дин и Ги де Лузиньян после битвы при Хаттине в 1187 году как пример настоящего холивара.
Салах ад-Дин и Ги де Лузиньян после битвы при Хаттине в 1187 году как пример настоящего холивара.

Для прекращения холивара в 1989 году была разработана программа pax. Разработка спонсировалась ассоциацией USENIX. Программа pax представляет собой объединение и унификацию tar и cpio. Кстати, в некоторых системах tar и cpio были просто символическими ссылками на pax. Считается, что название pax означает portable archive exchange, но мы то знаем, что холивар хотели завершить миром, ведь с латыни слово pax переводится как мир.

Как размножаются архиваторы.
Как размножаются архиваторы.

Действительно, в своё время были ярые сторонники как tar, так и cpio. Но в наше время для создания архивов в UNIX-подобных системах практически всегда используется tar. Многие форматы пакетов ПО в разных дистрибутивах LInux используют tar под капотом, исключение представляет RPM — там как раз cpio. Т.е. вместо двух программ, tar и cpio, теперь существует три.

Пожалуй, стоит ещё отметить, что обе программы и cpio, и tar были стандартизированы в POSIX.1-1988. И хотя в POSIX.1-2001 и cpio, и tar заменили на pax, tar и сейчас живее всех живых.

Компрессия и tar

Пользователи компьютеров, которые мало сталкиваются с UNIX-подобными ОС, зачастую привыкли к тому, что программа архивации одновременно является и программой компрессии, т.е. создаёт уже сжатый файл. Однако, это не UNIX way. В UNIX-подобных ОС другая парадигма. Как любил говаривать Малкольм Дуглас Макилрой: «Пишите программы, которые делают что-то одно и делают это хорошо.»

Слева Дуг Макилрой, справа Деннис Ритчи, смотрите не перепутайте.
Слева Дуг Макилрой, справа Деннис Ритчи, смотрите не перепутайте.

Программа tar полностью соответствует этому принципу, т.е. делает что-то одно — архивирует файлы. И, надо сказать, делает это хорошо, раз мы всё ещё пользуемся tar спустя более 45 лет после её создания. «Постойте!» — скажет читатель: «Зачем Вы обманываете? Ведь tar делает .tar.gz архивы, т.е. сжимает данные.» А вот тут как раз вступает в игру ещё одна поговорка Дуга Макилроя: «Пишите программы, которые бы работали вместе.» Программа tar и тут не отстаёт и работает в связке с другими программами — компрессорами, т.е. просто напросто вызывает их для компрессии и декомпрессии архива.

Программа tar такая старая, что пережила несколько популярных программ компрессии. Сейчас расширение файла .tar.gz выглядит привычно, и даже немного архаично (т.к. часто начинает встречаться .tar.xz), но ведь программа gzip появилась только в 1992 году. А до этого же как-то сжимали архивы tar? Сжимали. Наверное, первая популярная программа компрессии назвалась неожиданно — compress, и была выпущена в 1985 году. Расширение у файла архива при использовании compress было .tar.Z.

Мне также доводилось работать с компрессором freeze. Архивы были с расширениями .tar.F. (Чувствуете, как раньше любили прописные буквы?) Для декомпрессии использовалась программа melt — автор был с юмором, т.к. «freeze» и «melt» с английского переводятся как «замораживать» и «растапливать» соответственно. Кстати, бывали проблемы при отправке архива .tar.F по электронной почте, т.к. почтовик умудрялся присваивать MIME тип text/x-fortran, что приводило к повреждению отправляемых файлов. Программа freeze это довольно старый компрессор, вторая мажорная версия которого была выпущена никак не раньше 1991 года, а про первую версию мне сходу информацию найти не удалось.

Пожалуй, пора заканчивать обзор компрессоров. Стоит отметить, что современные версии tar поддерживают опции для указания типа сжатия, а по сути используемой программы компрессии. Опция z используется для gzip. Опция сжатия j — для bzip2. Позже появилась J — для xz. Например, tar Jcf имя.tar.xz ... Для компрессии при помощи программы compress предназначена опция Z.

Кстати, для распаковки, не нужно указывать тип сжатия, т.к. современные версии tar распознают алгоритм компрессии автоматически. Иными словами, достаточно tar xf имя.tar.gz.

Но так было не всегда.

Философия UNIX на примере tar

Интересно, как работали с версиями tar, которые не поддерживали компрессию и декомпрессию? Можем представить чисто гипотетическую ситуацию, что читатель оказался, например, на удалённом UNIX сервере, со старой версией tar. Или tar там не GNU и не BSD. Как на этом сервере создать сжатый архив? И как его распаковать?

Конечно, самый простой вариант это последовательный вызов команд:

tar cf tarball.tar ...
gzip tarball.tar

Кстати, обратили внимание, что исходный архив tarball.tar не нужно удалять? Программа gzip делает это автоматически, т.к. чаще всего исходный файл после сжатия не требуется. Если исходный файл всё-таки нужно сохранить, то следует использовать ключ -k (keep).

«Но ведь это неудобно!» — возмутится читатель. И будет прав. Две команды вместо одной. Да ещё и промежуточный файл. Мы же оказались всё-таки на UNIX сервере, а значит можем объединять команды в конвейер:

tar c ... | gzip - > tarball.tar.gz

В этом случае tar формирует архив и «записывает» его в стандартный поток вывода. Команда tar по умолчанию, т.е. без ключа f, работает со стандартными потоками ввода и вывода. В свою очередь, gzip принимает данные не из файла, а из стандартного потока ввода, об этом его просит одиночный - (дефис). На самом деле можно и дефис не указывать, т.к. gzip тоже по умолчанию работает со стандартными потоками ввода и вывода. Результат работы при помощи > перенаправляется в файл tarball.tar.gz.

С упаковкой разобрались. Как быть с распаковкой? Здесь гораздо неприятней, т.к. показанная ниже последовательность команд приведёт к утрате оригинального сжатого архива:

gzip -d tarball.tar.gz
tar xf tarball.tar

Если нельзя терять оригинальный сжатый архив, то можно его сохранить следующим образом:

gzip -k -d tarball.tar.gz
tar xf tarball.tar

Теперь получили два архива — сжатый и нет — tarball.tar.gz и tarball.tar. Можно, конечно, удалить промежуточный файл при помощи команды rm. Но снова вспоминаем, что мы находимся на UNIX сервере и можем объединять команды в конвейер:

zcat tarball.tar.gz | tar x

Программа zcat (или gzcat) выполняет декомпрессию в стандартный поток вывода, т.е. действует очень похоже на команду cat. Команда tar принимает данные со стандартного потока ввода и распаковывает архив.

Кстати, подход с *cat используется и другими компрессорами — bzcat, xzcat, zstdcat, хотя современные версии tar поддерживают эти компрессоры. Почему? Ну, во-первых, это красиво может быть полезно само по себе. Во-вторых, новая программа компрессии может использоваться со старой версией tar.

Помимо zcat программа компрессии зачастую представляет и другие утилиты, например, zless и zdiff, которые действуют аналогично less и diff, но для сжатых файлов. Другие программы компрессии тоже стараются не отставать.

Аргументы командной строки tar

Дотошный читатель должен был обратить внимание на одну особенность ключей командной строки программы tar — почему-то во всех предыдущих примерах не указан - (дефис) перед опциями. Эта особенность связана с тем, что программа tar разрабатывалась так давно, что привычные нам сегодня схемы работы с короткими и длинными опциями командной строки ещё не существовали. Или не были так популярны. Другим примером долгоживущей известной программы с непривычными опциями является dd.

Режим, когда опции команде tar передаются без дефиса называется традиционным. В этом случае после имени программы указывается блок опций, а затем в порядке расположения опций в блоке опций отдельными блоками указываются параметры опций, если они требуются. Например, следующие команды выполняют аналогичные действия:

tar tvf tarball.tar
tar tfv tarball.tar
tar fvt tarball.tar

Все три команды делают одно и то же — выводят список файлов на экран (в стандартный поток вывода). Порядок опций неважен, т.к. только одна из них (f) требует обязательный параметр (имя файла архива). Лично мне очень нравятся опции в традиционном стиле tar, без дефисов.

Ситуация меняется кардинальным образом, если добавить дефис перед блоком опций. В этом случае команда tar будет обрабатывать опции в стиле UNIX (короткие опции). И только первая команда выведет список файлов архива.

tar -tvf tarball.tar
tar -tfv tarball.tar
tar -fvt tarball.tar

Вторая команда сообщит, что не смогла открыть файл с именем v, если, конечно, файла с таким именем не оказалось в текущем каталоге. Если же, по счастливому стечению обстоятельств, в текущем каталоге отказался tar-архив с простым именем v, то команда попытается вывести информацию по файлу tarball.tar, который содержится в архиве с именем v. Надеюсь, что вы не забыли такой файл поместить в архив, а то получите ещё одно сообщение об ошибке.

Третья команда отругает пользователя за то, что он не указал одну из обязательным опций — -c, -r, -t, -u или -x. Это всё потому, что опция -f принимает остаток строки vt в качестве имени архива.

Получается, что в случае использования коротких опций (в стиле UNIX) порядок самих опций имеет значение. На самом деле порядок опций стоит соблюдать и при использовании традиционного стиля опций. Почему? Никогда не знаешь, когда может понадобиться извлечь из истории команду tar с опциями в традиционном стиле и добавить к команде длинную опцию, например, для указания владельца и группы файлов в архиве. Например, такая команда, которая просто создаёт архив:

tar cf tarball.tar ...

Легко и на автомате превращается в следующую команду:

tar --owner=root --group=root -cf tarball.tar ...

Нужно только добавить --owner=root --group=root - (включая дефис перед блоком опций) после имени программы tar.

Таким образом по моему опыту удобнее располагать аргументы командной строки tar в следующем порядке:

tar [длинные опции] [-][группа коротких опций][f] имя_архива имена_файлов...

Т.е. вначале указываются длинные опции, потом короткие, последняя из которых f (если она нужна), потом имена файлов. Если длинные опции в команде не используются, то я не ставлю дефис перед группой коротких опций. Почему? Во-первых, так на один символ короче. Во-вторых, выглядит более «лампово».

Кстати, для ряда относительно новых программ компрессии у tar нет коротких опций. Например, для сжатия при помощи программы zstd нужно указывать длинную опцию --zstd:

tar --zstd -cf tarball.tar.zst ...

Внимательный читатель легко догадается, как в одну составную команду подготовить архив, сжатый при помощи какой-либо новой программы компрессии. Да точно также, как подготовить архив .tar.gz на гипотетическом старом UNIX сервере.

Напоследок в качестве бонуса приведу команду, которую использую для подготовки архивов к передаче за пределы своей системы:

tar --owner=root --group=root --zstd -cf tarball_$(date +%Y%m%d).tar.zst ...

В результате получится архив, в котором отсутствует информация о локальном пользователе (имя владельца и группы файлов), всё равно при распаковке владелец и группа скорее всего будут заменены атрибутами текущего пользователя. Сам архив будет сжат компрессором Zstandard, который относительно быстро сжимает и ещё быстрее разжимает архив, а также обеспечивает приемлемую степень компрессии. К имени архива будет добавлена текущая дата в формате год, месяц и день, что помимо прочего позволит достаточно просто сортировать файлы архивов по дате создания.

Пожалуйста, не стесняйтесь и напишите в комментариях, было ли для вас что-то интересное или даже полезное в этой заметке? А может быть хотите поделиться какими-то интересными нюансами tar?

Теги:
Хабы:
+15
Комментарии22

Публикации

Работа

Ближайшие события