Learning Platform
Глоссарий Troubleshooting
Урок 14.01 · 22 мин
Начальный
tararchivecompressiontape archive

tar: основы архивирования

tar — это самая старая (с 1979 года) и до сих пор самая используемая утилита Linux/UNIX для архивирования. Аббревиатура расшифровывается как Tape ARchive — изначально для записи на ленточные накопители. Сейчас ленту никто не использует, но tar остался как стандарт упаковки множества файлов в один.

В DE-сценариях tar встречается ежедневно: бэкапы директорий, distribution package (.tar.gz файлы — это tar + gzip), packaging Python пакетов (.tar.gz есть на PyPI), Docker image layers (tar внутри).

Docker image layers — tar под капотом

В этом уроке — базовые операции с tar.


Что делает tar

Tar объединяет много файлов в один. Не сжимает — для сжатия используются отдельные утилиты (gzip, bzip2, xz, zstd). Это историческая особенность: tar родился до compression utilities, и был придуман для записи на ленту (которая сама может или не может сжимать).

Поэтому стандартный паттерн:

  • tar.gz (или .tgz) = tar + gzip — самый распространённый
  • tar.bz2 (или .tbz2) = tar + bzip2 — смалпее но медленнее
  • tar.xz (или .txz) = tar + xz — ещё меньше но ещё медленнее
  • tar.zst = tar + zstd — современный, быстрый и хорошее сжатие
tar: что делает и не делает

Архивирование != сжатие. tar делает archive, сжатие — отдельный шаг

dir/Множество файлов в директории
tar
dir.tarОдин файл-архив. Содержит все исходные файлы + метаданные (права, время). Размер ≈ сумма размеров. БЕЗ СЖАТИЯ
dir.tarАрхив без сжатия
gzip
dir.tar.gzСжатый архив. Намного меньше для текста (CSV, JSON, лога). Для уже-сжатых данных (JPEG, ZIP, parquet) — почти без эффекта

Главные modes: c, x, t

У tar три основных режима работы:

Modes tar — выбери один

Без указания режима tar не знает, что делать

c — CreateСоздать новый архив
x — eXtractРаспаковать архив
t — lisTПоказать содержимое без распаковки

Запомнить мнемонику: Create, eXtract, lisT. В команде эти буквы — первый аргумент:

# Создать архив
tar c ...

# Распаковать
tar x ...

# Просмотреть
tar t ...

Флаги-модификаторы: v, f

Без модификаторов tar — молчаливый и неудобный. Главные:

  • v (verbose) — выводить имена файлов по мере обработки.
  • f (file) — следующий аргумент это имя архива. БЕЗ f tar пишет/читает stdin/stdout!
# Без f — tar пытается читать с tape device /dev/st0 (или похожего)
# Этот флаг практически всегда нужен

# Create + verbose + file: создать архив archive.tar с содержимым dir/
tar cvf archive.tar dir/

# Extract + verbose + file
tar xvf archive.tar

# List + verbose + file
tar tvf archive.tar

Современный стиль допускает дефис: tar -cvf (как обычные команды). Но многие пишут без дефиса по привычке — оба варианта работают.

WARNING

Часто видишь команду tar xvf archive.tar без понимания, что значат буквы. Запомните: f ВСЕГДА должно быть, иначе tar попробует общаться с tape device. x или c — выбор режима. v — опционально.


Сжатие inline: z, j, J, —zstd

Чтобы не делать tar | gzip отдельным шагом, tar умеет интегрировать сжатие:

Флаги для сжатия в tar

Один шаг — tar + compression

z — gziptar.gz / .tgz. Самый частый, fast, не самый малый размер
j — bzip2tar.bz2. Меньше чем gzip, но медленнее
J — xztar.xz. Самое лучшее сжатие из старых, самое медленное
--zstd.tar.zst. Современный — быстрый как gzip + сжатие близкое к xz. Идеален для DE
# Создать tar.gz
tar czvf archive.tar.gz dir/

# Распаковать tar.gz
tar xzvf archive.tar.gz

# Аналогично для bzip2, xz
tar cjvf archive.tar.bz2 dir/
tar xjvf archive.tar.bz2

tar cJvf archive.tar.xz dir/
tar xJvf archive.tar.xz

# Для zstd — отдельный флаг
tar --zstd -cvf archive.tar.zst dir/
tar --zstd -xvf archive.tar.zst

Современный tar (gnu-tar) умеет автоопределение по расширению при extract:

# tar сам поймёт что это gzip по расширению
tar xvf archive.tar.gz
tar xvf archive.tar.bz2
tar xvf archive.tar.xz
tar xvf archive.tar.zst

Поэтому при extract достаточно xvf, не указывая флаг сжатия. При create — нужно указать.


Создание: примеры

# Базовое — содержимое директории
tar czvf backup.tar.gz /home/levo/data/

# Несколько объектов в один архив
tar czvf logs.tar.gz /var/log/airflow/ /var/log/postgres/

# Из текущей директории
cd /home/levo/data
tar czvf ~/backup.tar.gz .
# . = текущая директория. В архиве будут пути relative от текущей

# С абсолютными путями (плохо — при распаковке создаст /home/levo/...)
tar czvf bad.tar.gz /home/levo/data/

# Лучше — относительные пути
cd /home/levo && tar czvf data-backup.tar.gz data/

# Архив stdin (без файла, прямо в pipe)
tar czf - dir/ | ssh remote "cat > /backup/dir.tar.gz"
# - = stdout. Удобно для пайпов.

# С exclude
tar czvf code.tar.gz --exclude='*.pyc' --exclude='__pycache__' /home/levo/project/

Извлечение

# Базовое
tar xvf archive.tar.gz

# В конкретную директорию
tar xvf archive.tar.gz -C /tmp/extract-here/

# Только конкретный файл
tar xvf archive.tar.gz path/to/file.txt

# Удалить топовую директорию (часто нужно)
tar xvf archive.tar.gz --strip-components=1
# Например, архив содержит project-v1.0/src/main.py
# Без --strip — извлечётся в project-v1.0/src/main.py
# С --strip-components=1 — извлечётся в src/main.py (без project-v1.0)
TIP

--strip-components=N — must-know для распаковки source-tarball-ов. GitHub release tarball часто содержит repo-v1.0/ как верхнюю папку — tar xvf release.tar.gz --strip-components=1 распаковывает прямо в текущую директорию без обёртки.


Просмотр содержимого

# Список файлов в архиве
tar tvf archive.tar.gz

# Только имена (без размера/прав/времени)
tar tf archive.tar.gz

# С деталями: размер, права, время
tar tvf archive.tar.gz

# Сколько файлов в архиве
tar tf archive.tar.gz | wc -l

# Поиск по содержимому
tar tf archive.tar.gz | grep "specific-pattern"

tv показывает что-то типа:

drwxr-xr-x levo/levo  0 2026-05-13 14:23 data/
-rw-r--r-- levo/levo  1024 2026-05-13 14:23 data/file1.csv
-rw-r--r-- levo/levo  2048 2026-05-13 14:23 data/file2.csv

Колонки: permissions, owner/group, size, modification time, path.


Полезные опции

# Дозапись в существующий архив (только non-compressed!)
tar rvf archive.tar new-file.txt

# Сравнение архива с файлами (что изменилось?)
tar dvf archive.tar dir/

# Сохранять более точные timestamps
tar --acls --xattrs -czvf archive.tar.gz dir/
# --acls = POSIX ACLs
# --xattrs = extended attributes

# Не сохранять absolute paths
tar -P # сохранять (по умолчанию выключено)
tar -p # сохранять permissions (по умолчанию для root)

# Архивировать список файлов
tar czvf docs.tar.gz -T files.txt
# -T = take filenames from this file (one per line)

Пример с -T:

# Найти все CSV в /var/data
find /var/data -name '*.csv' > files-to-backup.txt

# Архивировать
tar czvf csvs.tar.gz -T files-to-backup.txt

Полезно когда список файлов больше, чем шrинка command-line.


DE-сценарии

1. Бэкап перед миграцией

# Перед изменением конфига Airflow — бэкап
sudo tar czvf /backup/airflow-config-$(date +%F).tar.gz /etc/airflow/

# Или с timestamp поминутным
sudo tar czvf /backup/airflow-config-$(date +%FT%H%M%S).tar.gz /etc/airflow/

2. Передача папки на другой сервер

# Архивировать локально
tar czf project.tar.gz ./project/
# Отправить через rsync (он умеет сжатие на лету, но для удобства можно tar)
rsync -avhP project.tar.gz remote:/tmp/
# На той стороне
ssh remote "cd /tmp && tar xzf project.tar.gz"

Альтернативно — pipe через ssh:

# Архивировать + передать в pipe без temporary file
tar czf - project/ | ssh remote "cd /destination && tar xzf -"

- означает stdout (на create) или stdin (на extract). Удобно когда нет места для temporary archive file.

3. Архивировать только старые файлы

# Найти .log файлы старше 7 дней, заархивировать
find /var/log/airflow -name '*.log' -mtime +7 -print0 | \
  tar czvf logs-archive-$(date +%F).tar.gz --null -T -

# Затем удалить (после проверки!)
find /var/log/airflow -name '*.log' -mtime +7 -delete

--null + -T - — читать имена файлов из stdin, разделённых nul-байтами. Безопаснее для файлов с пробелами/спецсимволами.

4. Распаковать Python source tarball

# Скачали с PyPI
curl -O https://files.pythonhosted.org/.../mypackage-1.0.tar.gz

# Извлечь без обёртки
mkdir mypackage && cd mypackage
tar xvf ../mypackage-1.0.tar.gz --strip-components=1

# Установить
pip install .

5. Inspect Docker image

# Docker image — это tar архив layers
docker save myimage:latest > myimage.tar

# Посмотреть структуру
tar tvf myimage.tar | head

# Это даст:
# manifest.json
# repositories
# <layer-hash>/layer.tar
# ...

Подводные камни

1. Absolute paths в архиве

# Плохо — архив содержит /home/levo/data/...
tar czvf bad.tar.gz /home/levo/data/

# При распаковке: tar xvf bad.tar.gz создаст /home/levo/... — не то место

Хорошо — относительные пути:

cd /home/levo && tar czvf data.tar.gz data/
# или
tar czvf data.tar.gz -C /home/levo data/
# -C сменить директорию перед добавлением

Современный tar предупреждает: «Removing leading `/’ from member names» — это безопасный default.

2. Permissions при распаковке от root vs user

Если архив создан от root (с разными owner) и распаковывается обычным пользователем — owner станет ваш user (вы не можете chown). Используйте —no-same-owner если хотите оставить как есть, или распакуйте от root.

3. Файлы с одинаковыми именами

# Если в архиве есть data/file.txt, и в текущей директории тоже —
# tar перепишет существующий
tar xvf archive.tar.gz

# Не переписывать существующие
tar xvf archive.tar.gz --skip-old-files

# Переписать только если файл в архиве новее
tar xvf archive.tar.gz --keep-newer-files

Попробуй сам

# 1. Создать тестовую директорию
mkdir -p /tmp/tar-test/dir1/sub
echo "file1" > /tmp/tar-test/dir1/file1.txt
echo "file2" > /tmp/tar-test/dir1/sub/file2.txt
echo "file3" > /tmp/tar-test/dir1/file3.txt

# 2. Создать tar (без сжатия)
cd /tmp/tar-test
tar cvf archive.tar dir1/
ls -lh archive.tar

# 3. Создать tar.gz (со сжатием)
tar czvf archive.tar.gz dir1/
ls -lh archive.tar*

# 4. Посмотреть содержимое
tar tvf archive.tar.gz

# 5. Распаковать в другую директорию
mkdir extracted
tar xvf archive.tar.gz -C extracted/
ls -R extracted/

# 6. С --strip-components
mkdir extracted2
tar xvf archive.tar.gz --strip-components=1 -C extracted2/
ls -R extracted2/

# 7. Извлечь конкретный файл
tar xvf archive.tar.gz dir1/file1.txt
cat dir1/file1.txt

# 8. Через pipe
tar czf - dir1/ | (cd /tmp && tar xzf -)

# 9. С исключениями
tar czvf no-sub.tar.gz dir1/ --exclude='*/sub/*'
tar tvf no-sub.tar.gz

# 10. Cleanup
rm -rf /tmp/tar-test

Cross-link: следующий урок 02 — детально про форматы сжатия (gzip vs zstd). Урок 04 — production DE workflows с tar.


Проверка знанийKnowledge check
Объясни команду tar -czvf project.tar.gz --exclude='__pycache__' /home/levo/project/ — каждая буква флагов, что значит, и почему стоит/не стоит её использовать в DE-сценариях.
ОтветAnswer
Разбор: -c (create) — создать новый архив. -z (gzip) — встроенное gzip-сжатие, файл становится .tar.gz. -v (verbose) — выводить имена файлов как обрабатываются (полезно для отладки и видимости прогресса, но для cron-скриптов лишний шум — можно убрать). -f project.tar.gz — следующий аргумент имя архива (без -f tar пишет в stdout/tape — обязательный флаг). --exclude='__pycache__' — пропустить любую директорию/файл __pycache__ (это Python bytecode-кэш, не нужен в архиве проекта). /home/levo/project/ — что архивируем. Что плохого: trailing slash на source-пути — tar архивирует с абсолютными путями (с предупреждением «Removing leading /»), но при распаковке создаст /home/levo/project/... — обычно не то место. Лучше: cd /home/levo && tar -czvf project.tar.gz --exclude='__pycache__' project/ — relative paths, при распаковке создаст ./project/ относительно текущей директории. Или tar -czvf project.tar.gz -C /home/levo --exclude='__pycache__' project/. -C меняет cwd перед added. Для production-скриптов также добавь --exclude='.git' --exclude='node_modules' --exclude='.venv' (стандартный набор для backup кода).

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Какая разница между `tar cvf archive.tar dir/` и `tar czvf archive.tar.gz dir/`?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4