Изучение команды Tar в Linux: сжатие и извлечение файлов

Команда tar определенно не является одной из самых простых для изучения команд Linux, и все эти флаги могут оказаться довольно запутанными!

Команда Linux tar используется для создания архивов .tar, .tar.gz, .tgz или tar.bz2, часто называемых «tarballs». Расширения .tar.gz и .tgz используются для идентификации архивов, созданных с помощью сжатия gzip для уменьшения размера архива. Архивы с расширением .tar.bz2 создаются с помощью сжатия bzip2.

Дистрибутивы Linux предоставляют tar-бинарный файл, который поддерживает сжатие gzip без помощи внешних команд. Это может не относиться к другим типам сжатия, как мы увидим в этой статье.

Давайте рассмотрим примеры команд tar, чтобы ознакомиться с наиболее распространенными флагами.

Как создать файл архива Tar: изучите синтаксис?

Вот простой пример синтаксиса команды tar.

Откройте командную строку Linux и следуйте всем командам, пока мы их рассматриваем.

Используйте следующую команду из текущего каталога. В этом примере мы не используем сжатие:

tar -cf archive.tar testfile1 testfile2

Эта команда позволяет создать архивный файл с именем archive.tar, содержащий два файла: testfile1 и testfile2. Мы создаем архивный файл, используя два флага: c и f.

Вот значение двух флагов:

Опция -c (то же, что и –-create): создать новый архив

Параметр -f: позволяет указать файл архива (в данном случае называемый archive.tar)

Команда Linux file подтверждает, что archive.tar является архивом:

[myuser@localhost]$ file archive.tar 
archive.tar: POSIX tar archive (GNU)

Еще один полезный флаг — флаг -v, который обеспечивает подробный вывод файлов, обработанных при запуске tar.

Давайте посмотрим, как изменится вывод, если при создании архива мы также передадим флаг -v:

[myuser@localhost]$ tar -cfv archive.tar testfile1 testfile2
tar: archive.tar: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

Странно, по какой-то причине мы получаем ошибку…

Это связано с тем, что команда tar создает архив с именем, основанным на том, что следует за флагом -f, а в данном случае после флага -f стоит флаг v.

Результатом является архив с именем v, как вы можете видеть из вывода ls ниже:

[myuser@localhost]$ ls -al
total 20
drwxrwxr-x. 2 myuser mygroup  4096 Jul 17 09:42.
drwxrwxrwt. 6 root     root      4096 Jul 17 09:38..
-rw-rw-r--. 1 myuser mygroup     0 Jul 17 09:38 testfile1
-rw-rw-r--. 1 myuser mygroup     0 Jul 17 09:38 testfile2
-rw-rw-r--. 1 myuser mygroup 10240 Jul 17 09:42 v

[myuser@localhost]$ file v
v: POSIX tar archive (GNU)

Ошибка «Нет такого файла или каталога» вызвана тем, что tar создает архив с именем v, содержащий три файла: archive.tar, testfile1 и testfile2. Но archive.tar не существует, отсюда и ошибка.

Это показывает, насколько важен порядок флагов, передаваемых команде tar.

Давайте поменяем местами флаги -f и -v в команде tar и попробуем еще раз:

[myuser@localhost]$ tar -cvf archive.tar testfile1 testfile2
testfile1
testfile2

На этот раз все хорошо, флаг verbose показывает имена двух файлов, добавляемых в создаваемый нами архив.

Мы увидели, как добавить несколько файлов в архив tar.

Имеет ли это смысл?

Как просмотреть список всех файлов в архиве Tar?

Чтобы вывести список всех файлов в архиве tar без извлечения его содержимого, мы введем четвертый флаг: -t.

Теперь мы можем объединить три флага: -t, -v и -f, чтобы увидеть файлы в архиве, который мы создали ранее:

[myuser@localhost]$ tar -tvf archive.tar 
-rw-rw-r-- myuser/mygroup 0 2020-07-17 09:38 testfile1
-rw-rw-r-- myuser/mygroup 0 2020-07-17 09:38 testfile2

Одна из вещей, которую я заметил, когда начал использовать команду tar, заключается в том, что разные люди запускают ее немного по-разному.

Я объясню, что я имею в виду, в следующем разделе…

Нужен ли тире в синтаксисе команды Tar?

Я заметил, что в некоторых случаях тире перед флагами присутствовало, но так было не всегда.

Итак, давайте посмотрим, имеет ли значение прохождение тире или нет.

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

[myuser@localhost]$ tar tvf archive.tar 
-rw-rw-r-- myuser/mygroup 0 2020-07-17 09:38 testfile1
-rw-rw-r-- myuser/mygroup 0 2020-07-17 09:38 testfile2

Вывод тот же, это значит, что тире не нужно.

Чтобы дать вам представление, вы можете запустить команду tar следующими способами и получить тот же результат:

tar -t -v -f archive.tar 
tar -tvf archive.tar
tar -tvf archive.tar
tar --list --verbose --file archive.tar

Последняя команда использует стиль длинных опций для флагов, передаваемых командам Linux.

Вы видите, насколько проще использовать короткую версию флагов.

Как извлечь все файлы из архива Tar в Linux

Давайте представим дополнительный флаг, который можно использовать для извлечения архива. Это флаг -x.

Давайте извлечем tar-файл, который мы создали ранее (вы также можете услышать термин «untar»).

Используйте команду Linux tar ниже:

[myuser@localhost]$ tar -xvf archive.tar
testfile1
testfile2
[myuser@localhost]$ ls -al
total 20
drwxrwxr-x 2 myuser mygroup    59 Feb 10 21:21.
drwxr-xr-x 3 myuser mygroup    55 Feb 10 21:21..
-rw-rw-r-- 1 myuser mygroup 10240 Feb 10 21:17 archive.tar
-rw-rw-r-- 1 myuser mygroup    54 Feb 10 21:17 testfile1
-rw-rw-r-- 1 myuser mygroup    78 Feb 10 21:17 testfile2 

Как видите, мы использовали флаг -x для извлечения содержимого архива, флаг -v, чтобы сделать это подробно, и флаг -f, чтобы сослаться на файл архива, указанный после флагов (archive.tar).

ПРИМЕЧАНИЕ: Как упоминалось ранее, мы вводим символ тире только один раз перед всеми флагами. Вместо этого мы могли бы указать символ тире перед каждым флагом, и вывод был бы таким же.

tar -x -v -f archive.tar

Как извлечь один файл из архива Tar

Также существует способ извлечь отдельный файл из архива.

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

Это очень распространенная ситуация, если у вас есть скрипт резервного копирования, который создает архив файлов журнала за последние 30 дней, и вы хотите просмотреть содержимое файла журнала только за определенный день.

Чтобы извлечь только testfile1 из archive.tar, можно использовать следующий общий синтаксис:

tar -xvf {archive_file} {path_to_file_to_extract}

А в нашем конкретном случае:

tar -xvf archive.tar testfile1

Давайте посмотрим, что изменится, если я создам tar-архив, содержащий два каталога:

[myuser@localhost]$ ls -ltr
total 8
drwxrwxr-x. 2 myuser mygroup 4096 Jul 17 10:34 dir1
drwxrwxr-x. 2 myuser mygroup 4096 Jul 17 10:34 dir2
[myuser@localhost]$ tar -cvf archive.tar dir*
dir1/
dir1/testfile1
dir2/
dir2/testfile2

Примечание: Обратите внимание, что я использовал подстановочный знак *, чтобы включить в архив любые файлы или каталоги, имена которых начинаются с «dir».

Следующая команда извлечет только testfile1:

tar -xvf archive.tar dir1/testfile1

После извлечения исходная структура каталогов сохраняется, поэтому в итоге мы получим testfile1 внутри dir1:

[myuser@localhost]$ ls -al dir1/
total 8
drwxrwxr-x. 2 myuser mygroup 4096 Jul 17 10:36.
drwxrwxr-x. 3 myuser mygroup 4096 Jul 17 10:36..
-rw-rw-r--. 1 myuser mygroup    0 Jul 17 10:34 testfile1

Теперь вы знаете, как извлечь определенные файлы из tar-архива.

Как можно использовать сжатие для уменьшения размера архива Tar?

Все файлы tar, которые мы создали до сих пор, были несжатыми. Допустим, мы хотим также сжать наши архивы.

Как мы это делаем?

Форматы сжатия Gzip и Bzip2 могут быть использованы для уменьшения размера архива tar. Дополнительные флаги tar для включения сжатия:

  • -z для Gzip: длинный флаг -–gzip
  • -j для Bzip2: длинный флаг –-bzip2

Чтобы создать сжатый архив tar с именем archive.tar.gz и подробным выводом, выполните следующую команду (также одну из наиболее распространенных команд, используемых при создании архивов tar):

tar -czvf archive.tar.gz testfile1 testfile2

И для извлечения его содержимого мы будем использовать:

tar -xzvf archive.tar.gz

Это также одна из основных команд при работе с tar.

Обратите внимание, как в имени созданного файла мы добавляем расширение .gz к предыдущему расширению tar.

Мы могли бы также использовать расширение .tgz вместо .tar.gz, и результат был бы тем же.

Теперь давайте создадим архив, использующий bzip2:

[myuser@localhost]$ tar -cvjf archive.tar.bz2 testfile*
testfile1
testfile2
/bin/sh: bzip2: command not found
tar: Child returned status 127
tar: Error is not recoverable: exiting now

Ошибка «bzip2: command not found» показывает, что команда tar пытается использовать команду bzip2 для сжатия, но эта команда не найдена в нашей системе Linux.

Решение — установить bzip2. Процедура зависит от используемого вами дистрибутива Linux, в моем случае это CentOS, который использует YUM в качестве менеджера пакетов.

Давайте установим bzip2 с помощью следующей команды yum для CentOS/Fedora:

yum install bzip2

Или с помощью apt для debian-based дистрибутивов:

apt install bzip2

Я могу подтвердить, что двоичный файл bzip2 существует, используя команду which:

[myuser@localhost]$ which bzip2
/usr/bin/bzip2

А команда для создания сжатых архивов с помощью bzip2 следующая:

[myuser@localhost]$ tar -cvjf archive.tar.bz2 testfile*
testfile1
testfile2
[myuser@localhost]$ ls -al
total 16
drwxrwxr-x. 2 myuser mygroup 4096 Jul 17 10:45.
drwxrwxrwt. 6 root     root     4096 Jul 17 10:53..
-rw-rw-r--. 1 myuser mygroup  136 Jul 17 10:54 archive.tar.bz2
-rw-rw-r--. 1 myuser mygroup  128 Jul 17 10:45 archive.tar.gz
-rw-rw-r--. 1 myuser mygroup    0 Jul 17 10:44 testfile1
-rw-rw-r--. 1 myuser mygroup    0 Jul 17 10:44 testfile2

Все работает!

Кроме того, учитывая, что мне очень любопытно, я хочу посмотреть, в чем разница между двумя архивами (.tar.gz и .tar.bz2) в соответствии с командой Linux file:

[myuser@localhost]$ file archive.tar.gz 
archive.tar.gz: gzip compressed data, last modified: Fri Jul 17 10:45:04 2020, from Unix, original size 10240
[myuser@localhost]$ file archive.tar.bz2 
archive.tar.bz2: bzip2 compressed data, block size = 900k

Как видите, Linux может различать архивы, созданные с использованием двух разных алгоритмов сжатия.

Как сжать каталог с помощью Tar?

Давайте посмотрим, как заархивировать целый каталог, а не только файлы внутри него.

Создайте каталог с именем tar_example и внутри него два файла:

[myuser@localhost]$ mkdir tar_example
[myuser@localhost]$ touch tar_example/testfile1
[myuser@localhost]$ touch tar_example/testfile2

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

[myuser@localhost]$ tar -cvzf tar_example_dir.tar.gz tar_example 
a tar_example
a tar_example/testfile1
a tar_example/testfile2

Подтвердите, что файл tar был создан правильно, используя команду tar с опцией -t. Эта команда показывает содержимое файла tar.gz:

[myuser@localhost]$ tar -tvzf tar_example_dir.tar.gz 
drwxr-xr-x  0 myuser mygroup       0 Jul 17 11:04 tar_example/
-rw-r--r--  0 myuser mygroup       0 Jul 17 11:04 tar_example/testfile1
-rw-r--r--  0 myuser mygroup       0 Jul 17 11:04 tar_example/testfile2

Все выглядит хорошо!

Заключение

Каждый пользователь Linux должен знать, как сжимать и извлекать архивы с помощью команды tar.

В этой статье вы узнали о наиболее распространенных флагах, используемых с командой tar, о том, как создавать и извлекать архивные файлы в формате tar, а также о том, как создавать и извлекать сжатый архив tar.

Давайте еще раз повторим все параметры команды tar:

  • -c: создать новый архив
  • -f: позволяет указать имя файла архива
  • -t: вывести список содержимого архива
  • -v: подробный список обработанных файлов
  • -x: извлечь файлы из архива
  • -z: создать сжатые архивные файлы с помощью gzip
  • -j: используется для сжатия с помощью bzip2

А вы? Для чего вы используете tar в Linux?