tar
Упаковка каталогов в архив и распаковка — .tar, .tar.gz, .tar.xz, просмотр и выборочное извлечение
tar склеивает файлы и каталоги в один архив, сохраняя структуру, права, владельцев и время изменения. Сам по себе tar не сжимает — сжатие добавляется опцией: z (gzip, .tar.gz/.tgz), J (xz, .tar.xz).
Синтаксис
tar -c [опции] -f архив.tar файлы… # создать
tar -t [опции] -f архив.tar [файлы…] # показать содержимое
tar -x [опции] -f архив.tar [файлы…] # распаковать
Режим выбирается ровно один. Опции можно склеивать: tar -czf = tar -c -z -f. Старая запись без дефиса (tar czf) тоже работает.
Режимы
| Режим | Что делает |
|---|---|
-c | создать новый архив |
-t | показать список файлов в архиве |
-x | распаковать |
-r | дописать файлы в конец архива (только несжатый .tar) |
-u | дописать файлы, которые новее своих копий в архиве (только .tar) |
-A | дописать в архив содержимое другого .tar |
--delete | удалить файлы из архива (только .tar) |
-d | сравнить архив с файлами на диске: что отличается |
Архив и сжатие
| Опция | Что делает |
|---|---|
-f архив | имя файла архива; -f - — stdout/stdin |
-z | gzip (.tar.gz, .tgz) |
-J | xz (.tar.xz) — сильнее, но медленнее |
-j / --zstd | bzip2 / zstd — нужны одноимённые программы в системе |
-a | выбрать сжатие по расширению имени архива (при создании) |
-I 'команда' | сжимать произвольной программой: -I 'gzip -9', -I 'xz -T0' |
При чтении (-t, -x) сжатие можно не указывать: tar -xf архив.tar.xz определит его сам.
Какие файлы взять
| Опция | Что делает |
|---|---|
-C каталог | перейти в каталог перед работой: откуда брать файлы или куда распаковать |
--exclude='шаблон' | не включать подходящие файлы и каталоги на любом уровне (ставь до списка файлов) |
--anchored | следующие --exclude сравнивать с началом пути в архиве |
-X файл | шаблоны исключений из файла, по одному на строку |
--exclude-vcs | не включать .git, .svn и подобные |
-T список | взять имена файлов из файла (-T - — со stdin); с --null — разделённые нулевым байтом |
--newer-mtime='2024-01-01' | только файлы, изменённые после даты (каталоги попадают всегда) |
-g снимок | инкрементный архив: в следующий раз с тем же снимком попадут только изменения |
-h | класть в архив файлы, на которые указывают ссылки, а не сами ссылки |
--one-file-system | не переходить на другие файловые системы |
--remove-files | удалить исходные файлы после упаковки |
-P | сохранить абсолютные пути (ведущий /) — обычно не нужно |
Как распаковать
| Опция | Что делает |
|---|---|
--strip-components=N | отрезать первые N уровней пути |
--transform='s,^app,app-1.0,' | переименовать пути выражением как в sed (работает и при создании) |
--wildcards | разрешить шаблоны * в именах при -t/-x |
-O | распаковать в stdout, а не на диск |
-k | не перезаписывать существующие файлы (ошибка на каждом) |
--skip-old-files | молча пропускать существующие файлы |
--keep-newer-files | не перезаписывать файлы, которые на диске новее |
-m | не восстанавливать время изменения — поставить текущее |
-p | восстановить права точно, без учёта umask (для root включено по умолчанию) |
--no-same-owner | не восстанавливать владельцев — всё будет принадлежать тебе |
Владельцы в архиве и вывод
| Опция | Что делает |
|---|---|
-v | печатать имена файлов; -vv или -tv — подробно |
--owner=root --group=root | записать в архив другого владельца |
--numeric-owner | писать и читать владельцев только числами |
--totals | в конце напечатать, сколько байт записано |
-W | после создания проверить архив |
Строка tar -tvf: права, владелец/группа, размер в байтах, дата и время изменения, путь. Для ссылок — имя -> цель.
-rw-r--r-- alice/devs 2048 2024-05-01 12:00 app/config.yml
Примеры
# упаковать каталог со сжатием gzip; пути в архиве начнутся с app/
tar -czf app.tar.gz -C /srv app
# архив с датой в имени
tar -czf "backup-$(date +%F).tar.gz" -C /srv app
# без лишнего: исключения — до списка файлов
tar -czf app.tar.gz --exclude=node_modules --exclude='*.log' --exclude-vcs -C /srv app
# посмотреть содержимое, не распаковывая (сжатие tar определит сам)
tar -tf app.tar.gz
tar -tvf app.tar.gz
# распаковать в указанный каталог (он должен существовать)
mkdir -p /tmp/restore && tar -xzf app.tar.gz -C /tmp/restore
# распаковать без верхнего каталога архива
tar -xzf app.tar.gz -C /srv/app --strip-components=1
# достать один каталог или файлы по шаблону
tar -xzf app.tar.gz app/logs
tar -xzf app.tar.gz --wildcards '*.conf'
# вывести один файл на экран
tar -xOf app.tar.gz app/config.yml
# сравнить архив с файлами на диске
tar -df app.tar.gz -C /srv
# упаковать список файлов, найденных find
find /etc -name '*.conf' -mtime -7 -print0 | tar -czf recent-conf.tgz --null -T -
# полный бэкап и затем только изменения
tar -czf full.tgz -g /var/backups/app.snar -C /srv app
tar -czf incr-1.tgz -g /var/backups/app.snar -C /srv app
# сильное сжатие xz во все ядра
tar -I 'xz -T0' -cf app.tar.xz -C /srv app
# архив через конвейер — например, сразу на другую машину
tar -czf - -C /srv app | ssh backup@example.com 'cat > app.tar.gz'
Подводные камни
-fдолжен стоять последним в склейке. За ним идёт имя архива:tar -cfz app.tar appсоздаст архив с именемz, аapp.tarпопытается упаковать как файл.- Абсолютные пути.
tar -czf a.tgz /srv/appуберёт ведущий/и сохранитsrv/app/…— при распаковке получится./srv/app. Используй-C /srv app, чтобы в архиве был короткий путь. --excludeпосле списка файлов не действует. GNU tar предупредит («has no effect») и упакует всё; при этом архив создастся, но код возврата будет ненулевым.--excludeне привязан к началу пути.--exclude=cacheисключит иapp/cache, иapp/lib/cache— любой компонент пути с таким именем. Чтобы исключить толькоapp/cache, добавь--anchoredперед--exclude=app/cache.- Шаблоны при распаковке.
tar -xf a.tar '*.log'без--wildcardsищет файл с буквальным именем*.logи выдаёт «Not found in archive». - Распаковка перезаписывает файлы молча. Сначала посмотри список (
-t), распаковывай в пустой каталог или добавь-k/--skip-old-files. - Сжатый архив нельзя изменить.
-r,-u,-A,--deleteработают только с несжатым.tar: «Cannot update compressed archives». - Пустой список файлов — ошибка «Cowardly refusing to create an empty archive». Так бывает, когда
findдля-Tничего не нашёл. - Владельцы. root при распаковке восстанавливает владельцев из архива. Обычный пользователь получает все файлы на себя.
- bzip2 и zstd может не быть.
tar -jи--zstdвызывают внешние программы и без них упадут с «not found».